]> git.basschouten.com Git - openhab-addons.git/blob
782383dbfe73f39e6d5b1d5c952668325d4ee1b4
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.nanoleaf.internal.layout;
14
15 import java.awt.Color;
16 import java.awt.Graphics2D;
17 import java.awt.RenderingHints;
18 import java.awt.image.BufferedImage;
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.util.List;
22
23 import javax.imageio.ImageIO;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.openhab.binding.nanoleaf.internal.NanoleafBindingConstants;
27 import org.openhab.binding.nanoleaf.internal.layout.shape.Panel;
28 import org.openhab.binding.nanoleaf.internal.layout.shape.PanelFactory;
29 import org.openhab.binding.nanoleaf.internal.model.GlobalOrientation;
30 import org.openhab.binding.nanoleaf.internal.model.Layout;
31 import org.openhab.binding.nanoleaf.internal.model.PanelLayout;
32 import org.openhab.binding.nanoleaf.internal.model.PositionDatum;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Renders the Nanoleaf layout to an image.
38  *
39  * @author Jørgen Austvik - Initial contribution
40  */
41 @NonNullByDefault
42 public class NanoleafLayout {
43
44     private static final Logger logger = LoggerFactory.getLogger(NanoleafLayout.class);
45     private static final Color COLOR_BACKGROUND = Color.WHITE;
46
47     public static byte[] render(PanelLayout panelLayout, PanelState state, LayoutSettings settings) throws IOException {
48         double rotationRadians = 0;
49         GlobalOrientation globalOrientation = panelLayout.getGlobalOrientation();
50         if (globalOrientation != null) {
51             rotationRadians = calculateRotationRadians(globalOrientation);
52         }
53
54         Layout layout = panelLayout.getLayout();
55         if (layout == null) {
56             logger.warn("Returning no image as we don't have any layout to render");
57             return new byte[] {};
58         }
59
60         List<PositionDatum> positionDatums = layout.getPositionData();
61         if (positionDatums == null) {
62             logger.warn("Returning no image as we don't have any position datums to render");
63             return new byte[] {};
64         }
65
66         ImagePoint2D[] size = findSize(positionDatums, rotationRadians);
67         final ImagePoint2D min = size[0];
68         final ImagePoint2D max = size[1];
69
70         BufferedImage image = new BufferedImage(
71                 (max.getX() - min.getX()) + 2 * NanoleafBindingConstants.LAYOUT_BORDER_WIDTH,
72                 (max.getY() - min.getY()) + 2 * NanoleafBindingConstants.LAYOUT_BORDER_WIDTH,
73                 BufferedImage.TYPE_INT_RGB);
74         Graphics2D g2 = image.createGraphics();
75         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
76         g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
77         g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
78
79         g2.setBackground(COLOR_BACKGROUND);
80         g2.clearRect(0, 0, image.getWidth(), image.getHeight());
81
82         DrawingSettings dc = new DrawingSettings(settings, image.getHeight(), min, rotationRadians);
83         List<Panel> panels = PanelFactory.createPanels(positionDatums);
84         for (Panel panel : panels) {
85             panel.draw(g2, dc, state);
86         }
87
88         ByteArrayOutputStream out = new ByteArrayOutputStream();
89         ImageIO.write(image, "png", out);
90         return out.toByteArray();
91     }
92
93     private static double calculateRotationRadians(GlobalOrientation globalOrientation) {
94         Integer maxObj = globalOrientation.getMax();
95         int maxValue = maxObj == null ? 360 : (int) maxObj;
96         int value = globalOrientation.getValue(); // 0 - 360 measured counter clockwise.
97         return ((double) (maxValue - value)) * (Math.PI / 180);
98     }
99
100     private static ImagePoint2D[] findSize(List<PositionDatum> positionDatums, double rotationRadians) {
101         int maxX = 0;
102         int maxY = 0;
103         int minX = 0;
104         int minY = 0;
105
106         List<Panel> panels = PanelFactory.createPanels(positionDatums);
107         for (Panel shape : panels) {
108             for (Point2D point : shape.generateOutline()) {
109                 var rotated = point.rotate(rotationRadians);
110                 maxX = Math.max(rotated.getX(), maxX);
111                 maxY = Math.max(rotated.getY(), maxY);
112                 minX = Math.min(rotated.getX(), minX);
113                 minY = Math.min(rotated.getY(), minY);
114             }
115         }
116
117         return new ImagePoint2D[] { new ImagePoint2D(minX, minY), new ImagePoint2D(maxX, maxY) };
118     }
119 }