Consider rotated panel layouts

This commit is contained in:
Lord-Grey 2023-10-05 22:31:46 +02:00
parent 15b6098d3c
commit a366f4c0cf
3 changed files with 67 additions and 23 deletions

View File

@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Nanoleaf: Wizard to generate user authorization token allowing users to configure the device via a single window - Nanoleaf: Wizard to generate user authorization token allowing users to configure the device via a single window
- Nanoleaf: Generation of a default layout per device's configuration - Nanoleaf: Generation of a default layout per device's configuration, including oriantation
### Changed ### Changed
@ -21,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Nanoleaf: "Panel numbering sequence" was not configurable any longer - Nanoleaf: "Panel numbering sequence" was not configurable any longer
- Nanoleaf: Number of panels increased during retries (#1643) - Nanoleaf: Number of panels increased during retries (#1643)
## Removed ### Removed
- Nanoleaf: Removed "Start Position" in favour of the general Blacklist feature provided - Nanoleaf: Removed "Start Position" in favour of the general Blacklist feature provided
## [2.0.15](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.15) - 2023-02 ## [2.0.15](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.15) - 2023-02

View File

@ -1697,7 +1697,7 @@ $(document).ready(function () {
if (ledDeviceProperties) { if (ledDeviceProperties) {
var panelOrderTopDown = conf_editor.getEditor("root.specificOptions.panelOrderTopDown").getValue() === "top2down"; var panelOrderTopDown = conf_editor.getEditor("root.specificOptions.panelOrderTopDown").getValue() === "top2down";
var panelOrderLeftRight = conf_editor.getEditor("root.specificOptions.panelOrderLeftRight").getValue() === "left2right"; var panelOrderLeftRight = conf_editor.getEditor("root.specificOptions.panelOrderLeftRight").getValue() === "left2right";
var ledArray = nanoleafGeneratelayout(ledDeviceProperties.panelLayout.layout, panelOrderTopDown, panelOrderLeftRight); var ledArray = nanoleafGeneratelayout(ledDeviceProperties.panelLayout, panelOrderTopDown, panelOrderLeftRight);
aceEdt.set(ledArray); aceEdt.set(ledArray);
isGenerated = true; isGenerated = true;
} }
@ -2480,8 +2480,14 @@ function sortByPanelCoordinates(arr, topToBottom, leftToRight) {
} }
}); });
} }
function rotateCoordinates(x, y, radians) {
var rotatedX = x * Math.cos(radians) - y * Math.sin(radians);
var rotatedY = x * Math.sin(radians) + y * Math.cos(radians);
function nanoleafGeneratelayout(layout, panelOrderTopDown, panelOrderLeftRight) { return { x: rotatedX, y: rotatedY };
}
function nanoleafGeneratelayout(panelLayout, panelOrderTopDown, panelOrderLeftRight) {
// Dictionary for Nanoleaf shape types // Dictionary for Nanoleaf shape types
let shapeTypes = { let shapeTypes = {
@ -2496,7 +2502,7 @@ function nanoleafGeneratelayout(layout, panelOrderTopDown, panelOrderLeftRight)
9: { name: "ShapesMiniTriangle", sideLengthX: 67, sideLengthY: 67 }, 9: { name: "ShapesMiniTriangle", sideLengthX: 67, sideLengthY: 67 },
12: { name: "ShapesController", sideLengthX: 0, sideLengthY: 0 }, 12: { name: "ShapesController", sideLengthX: 0, sideLengthY: 0 },
14: { name: "ElementsHexagon", sideLengthX: 134, sideLengthY: 134 }, 14: { name: "ElementsHexagon", sideLengthX: 134, sideLengthY: 134 },
15: { name: "ElementsHexagonCorner", sideLengthX: 33.5, sideLengthX: 58 }, 15: { name: "ElementsHexagonCorner", sideLengthX: 33.5, sideLengthY: 58 },
16: { name: "LinesConnector", sideLengthX: 11, sideLengthY: 11 }, 16: { name: "LinesConnector", sideLengthX: 11, sideLengthY: 11 },
17: { name: "LightLines", sideLengthX: 154, sideLengthY: 154 }, 17: { name: "LightLines", sideLengthX: 154, sideLengthY: 154 },
18: { name: "LightLinesSingleZone", sideLengthX: 77, sideLengthY: 77 }, 18: { name: "LightLinesSingleZone", sideLengthX: 77, sideLengthY: 77 },
@ -2505,20 +2511,36 @@ function nanoleafGeneratelayout(layout, panelOrderTopDown, panelOrderLeftRight)
999: { name: "Unknown", sideLengthX: 100, sideLengthY: 100 } 999: { name: "Unknown", sideLengthX: 100, sideLengthY: 100 }
}; };
let { positionData, numPanels, sideLength } = layout; let { globalOrientation, layout } = panelLayout;
var minX = positionData[0].x; var positionData = layout.positionData;
var maxX = positionData[0].x; var degreesToRotate = 0;
var minY = positionData[0].y; if (globalOrientation) {
var maxY = positionData[0].y; degreesToRotate = globalOrientation.value;
}
// Convert degrees to radians
var radians = (degreesToRotate * Math.PI) / 180;
var rotatedCoordinates = rotateCoordinates(positionData[0].x, positionData[0].y, radians);
var minX = rotatedCoordinates.x;
var maxX = rotatedCoordinates.x;
var minY = rotatedCoordinates.y;
var maxY = rotatedCoordinates.y;
//Define capture rectangle per panel //Define capture rectangle per panel
var factorPartial = 0.25; var factorPartial = 0.25;
positionData.forEach(panel => { positionData.forEach(panel => {
if (shapeTypes[panel.shapeType] == undefined) { if (shapeTypes[panel.shapeType] == undefined) {
panel.shapeType = 999; panel.shapeType = 999;
} }
if (radians !== 0) {
rotatedCoordinates = rotateCoordinates(panel.x, panel.y, radians);
panel.x = rotatedCoordinates.x;
panel.y = rotatedCoordinates.y;
}
panel.maxX = panel.x + shapeTypes[panel.shapeType].sideLengthX * factorPartial; panel.maxX = panel.x + shapeTypes[panel.shapeType].sideLengthX * factorPartial;
panel.maxY = panel.y + shapeTypes[panel.shapeType].sideLengthY * factorPartial; panel.maxY = panel.y + shapeTypes[panel.shapeType].sideLengthY * factorPartial;
panel.shapeName = shapeTypes[panel.shapeType].name; panel.shapeName = shapeTypes[panel.shapeType].name;
@ -2548,17 +2570,19 @@ function nanoleafGeneratelayout(layout, panelOrderTopDown, panelOrderLeftRight)
sortByPanelCoordinates(positionData, panelOrderTopDown, panelOrderLeftRight); sortByPanelCoordinates(positionData, panelOrderTopDown, panelOrderLeftRight);
positionData.forEach(panel => { positionData.forEach(panel => {
let layoutObject = { // Skip non-LED elements
name: i + "-" + panel.panelId, if (panel.sideLengthX !== 0) {
hmin: (panel.x - minX) * scaleX, let layoutObject = {
hmax: (panel.maxX - minX) * scaleX, name: i + "-" + panel.panelId,
//Nanoleaf corodinates start at bottom left, therefore reverse vertical positioning hmin: (panel.x - minX) * scaleX,
vmin: 1 - ((panel.maxY - minY) * scaleY), hmax: (panel.maxX - minX) * scaleX,
vmax: 1 - ((panel.y - minY) * scaleY) //Nanoleaf corodinates start at bottom left, therefore reverse vertical positioning
}; vmin: 1 - ((panel.maxY - minY) * scaleY),
++i; vmax: 1 - ((panel.y - minY) * scaleY)
};
layoutObjects.push(JSON.parse(JSON.stringify(layoutObject))); layoutObjects.push(JSON.parse(JSON.stringify(layoutObject)));
++i;
}
}); });
return layoutObjects; return layoutObjects;
} }

View File

@ -4,6 +4,7 @@
//std includes //std includes
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <cmath>
// Qt includes // Qt includes
#include <QNetworkReply> #include <QNetworkReply>
@ -39,6 +40,8 @@ namespace {
const int BRI_MAX = 100; const int BRI_MAX = 100;
// Panel configuration settings // Panel configuration settings
const char PANEL_GLOBALORIENTATION[] = "globalOrientation";
const char PANEL_GLOBALORIENTATION_VALUE[] = "value";
const char PANEL_LAYOUT[] = "layout"; const char PANEL_LAYOUT[] = "layout";
const char PANEL_NUM[] = "numPanels"; const char PANEL_NUM[] = "numPanels";
const char PANEL_ID[] = "panelId"; const char PANEL_ID[] = "panelId";
@ -240,6 +243,10 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
// Get panel details from /panelLayout/layout // Get panel details from /panelLayout/layout
QJsonObject jsonPanelLayout = jsonAllPanelInfo[API_PANELLAYOUT].toObject(); QJsonObject jsonPanelLayout = jsonAllPanelInfo[API_PANELLAYOUT].toObject();
const QJsonObject globalOrientation = jsonPanelLayout[PANEL_GLOBALORIENTATION].toObject();
double radians = (globalOrientation[PANEL_GLOBALORIENTATION_VALUE].toInt() * std::acos(-1)) / 180;
QJsonObject jsonLayout = jsonPanelLayout[PANEL_LAYOUT].toObject(); QJsonObject jsonLayout = jsonPanelLayout[PANEL_LAYOUT].toObject();
_panelLedCount = getHwLedCount(jsonLayout); _panelLedCount = getHwLedCount(jsonLayout);
@ -256,9 +263,22 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
QJsonObject panelObj = value.toObject(); QJsonObject panelObj = value.toObject();
int panelId = panelObj[PANEL_ID].toInt(); int panelId = panelObj[PANEL_ID].toInt();
int panelX = panelObj[PANEL_POS_X].toInt();
int panelY = panelObj[PANEL_POS_Y].toInt();
int panelshapeType = panelObj[PANEL_SHAPE_TYPE].toInt(); int panelshapeType = panelObj[PANEL_SHAPE_TYPE].toInt();
int posX = panelObj[PANEL_POS_X].toInt();
int posY = panelObj[PANEL_POS_Y].toInt();
int panelX;
int panelY;
if (radians != 0)
{
panelX = static_cast<int>(posX * cos(radians) - posY * sin(radians));
panelY = static_cast<int>(posX * sin(radians) + posY * cos(radians));
}
else
{
panelX = posX;
panelY = posY;
}
DebugIf(verbose, _log, "Panel [%d] (%d,%d) - Type: [%d]", panelId, panelX, panelY, panelshapeType); DebugIf(verbose, _log, "Panel [%d] (%d,%d) - Type: [%d]", panelId, panelX, panelY, panelshapeType);