mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Consider rotated panel layouts
This commit is contained in:
		@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- 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
 | 
			
		||||
 | 
			
		||||
@@ -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: Number of panels increased during retries (#1643)
 | 
			
		||||
 | 
			
		||||
## Removed
 | 
			
		||||
### Removed
 | 
			
		||||
- 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1697,7 +1697,7 @@ $(document).ready(function () {
 | 
			
		||||
        if (ledDeviceProperties) {
 | 
			
		||||
          var panelOrderTopDown = conf_editor.getEditor("root.specificOptions.panelOrderTopDown").getValue() === "top2down";
 | 
			
		||||
          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);
 | 
			
		||||
          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
 | 
			
		||||
  let shapeTypes = {
 | 
			
		||||
@@ -2496,7 +2502,7 @@ function nanoleafGeneratelayout(layout, panelOrderTopDown, panelOrderLeftRight)
 | 
			
		||||
    9: { name: "ShapesMiniTriangle", sideLengthX: 67, sideLengthY: 67 },
 | 
			
		||||
    12: { name: "ShapesController", sideLengthX: 0, sideLengthY: 0 },
 | 
			
		||||
    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 },
 | 
			
		||||
    17: { name: "LightLines", sideLengthX: 154, sideLengthY: 154 },
 | 
			
		||||
    18: { name: "LightLinesSingleZone", sideLengthX: 77, sideLengthY: 77 },
 | 
			
		||||
@@ -2505,20 +2511,36 @@ function nanoleafGeneratelayout(layout, panelOrderTopDown, panelOrderLeftRight)
 | 
			
		||||
    999: { name: "Unknown", sideLengthX: 100, sideLengthY: 100 }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let { positionData, numPanels, sideLength } = layout;
 | 
			
		||||
  var minX = positionData[0].x;
 | 
			
		||||
  var maxX = positionData[0].x;
 | 
			
		||||
  var minY = positionData[0].y;
 | 
			
		||||
  var maxY = positionData[0].y;
 | 
			
		||||
  let { globalOrientation, layout } = panelLayout;
 | 
			
		||||
  var positionData = layout.positionData;
 | 
			
		||||
  var degreesToRotate = 0;
 | 
			
		||||
  if (globalOrientation) {
 | 
			
		||||
    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
 | 
			
		||||
  var factorPartial = 0.25;
 | 
			
		||||
 | 
			
		||||
  positionData.forEach(panel => {
 | 
			
		||||
 | 
			
		||||
    if (shapeTypes[panel.shapeType] == undefined) {
 | 
			
		||||
      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.maxY = panel.y + shapeTypes[panel.shapeType].sideLengthY * factorPartial;
 | 
			
		||||
    panel.shapeName = shapeTypes[panel.shapeType].name;
 | 
			
		||||
@@ -2548,17 +2570,19 @@ function nanoleafGeneratelayout(layout, panelOrderTopDown, panelOrderLeftRight)
 | 
			
		||||
  sortByPanelCoordinates(positionData, panelOrderTopDown, panelOrderLeftRight);
 | 
			
		||||
  positionData.forEach(panel => {
 | 
			
		||||
 | 
			
		||||
    let layoutObject = {
 | 
			
		||||
      name: i + "-" + panel.panelId,
 | 
			
		||||
      hmin: (panel.x - minX) * scaleX,
 | 
			
		||||
      hmax: (panel.maxX - minX) * scaleX,
 | 
			
		||||
      //Nanoleaf corodinates start at bottom left, therefore reverse vertical positioning
 | 
			
		||||
      vmin: 1 - ((panel.maxY - minY) * scaleY),
 | 
			
		||||
      vmax: 1 - ((panel.y - minY) * scaleY)
 | 
			
		||||
    };
 | 
			
		||||
    ++i;
 | 
			
		||||
 | 
			
		||||
    layoutObjects.push(JSON.parse(JSON.stringify(layoutObject)));
 | 
			
		||||
    // Skip non-LED elements
 | 
			
		||||
    if (panel.sideLengthX !== 0) {
 | 
			
		||||
      let layoutObject = {
 | 
			
		||||
        name: i + "-" + panel.panelId,
 | 
			
		||||
        hmin: (panel.x - minX) * scaleX,
 | 
			
		||||
        hmax: (panel.maxX - minX) * scaleX,
 | 
			
		||||
        //Nanoleaf corodinates start at bottom left, therefore reverse vertical positioning
 | 
			
		||||
        vmin: 1 - ((panel.maxY - minY) * scaleY),
 | 
			
		||||
        vmax: 1 - ((panel.y - minY) * scaleY)
 | 
			
		||||
      };
 | 
			
		||||
      layoutObjects.push(JSON.parse(JSON.stringify(layoutObject)));
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  return layoutObjects;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
//std includes
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
#include <cmath>
 | 
			
		||||
 | 
			
		||||
// Qt includes
 | 
			
		||||
#include <QNetworkReply>
 | 
			
		||||
@@ -39,6 +40,8 @@ namespace {
 | 
			
		||||
	const int BRI_MAX = 100;
 | 
			
		||||
 | 
			
		||||
	// Panel configuration settings
 | 
			
		||||
	const char PANEL_GLOBALORIENTATION[] = "globalOrientation";
 | 
			
		||||
	const char PANEL_GLOBALORIENTATION_VALUE[] = "value";
 | 
			
		||||
	const char PANEL_LAYOUT[] = "layout";
 | 
			
		||||
	const char PANEL_NUM[] = "numPanels";
 | 
			
		||||
	const char PANEL_ID[] = "panelId";
 | 
			
		||||
@@ -240,6 +243,10 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
 | 
			
		||||
 | 
			
		||||
		// Get panel details from /panelLayout/layout
 | 
			
		||||
		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();
 | 
			
		||||
 | 
			
		||||
		_panelLedCount = getHwLedCount(jsonLayout);
 | 
			
		||||
@@ -256,9 +263,22 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
 | 
			
		||||
			QJsonObject panelObj = value.toObject();
 | 
			
		||||
 | 
			
		||||
			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 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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user