blue-chestnut-solar-expert 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/eraser-icon.house-icon.icon-selector.map-draw.map-selector.move-icon.octagon-minus-icon.polygon-buttons.polygon-information.search-icon.settings-icon.settings-modal.solar-expert.solar-system-form.tool-box.undo-icon.entry.cjs.js.map +1 -1
- package/dist/cjs/eraser-icon_16.cjs.entry.js +47 -45
- package/dist/cjs/eraser-icon_16.cjs.entry.js.map +1 -1
- package/dist/cjs/{index-C3Kp1xqq.js → index-elxiOP_I.js} +28 -5
- package/dist/cjs/index-elxiOP_I.js.map +1 -0
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/loading-widget.cjs.entry.js +2 -2
- package/dist/cjs/solar-calculator.cjs.entry.js +2 -2
- package/dist/cjs/stencil-library.cjs.js +2 -2
- package/dist/collection/components/map-draw/map-selector.js +1 -1
- package/dist/collection/components/map-draw/map-selector.js.map +1 -1
- package/dist/collection/components/settings/settings.js +8 -8
- package/dist/collection/components/settings/settings.js.map +1 -1
- package/dist/collection/components/solar-calculator/solar-calculator.js +1 -1
- package/dist/collection/components/solar-expert/solar-expert.js +6 -3
- package/dist/collection/components/solar-expert/solar-expert.js.map +1 -1
- package/dist/collection/components/solar-system-form/solar-system-form.js +31 -31
- package/dist/collection/components/widgets/loading-widget.js +1 -1
- package/dist/collection/store.js +1 -1
- package/dist/collection/store.js.map +1 -1
- package/dist/components/index.js +22 -4
- package/dist/components/index.js.map +1 -1
- package/dist/components/loading-widget.js +1 -1
- package/dist/components/map-draw.js +1 -1
- package/dist/components/map-selector.js +1 -1
- package/dist/components/{p-CUOVbcj0.js → p-B1ywivYa.js} +3 -3
- package/dist/components/{p-CUOVbcj0.js.map → p-B1ywivYa.js.map} +1 -1
- package/dist/components/{p-DRZd44KM.js → p-BGxYjXB5.js} +11 -11
- package/dist/components/p-BGxYjXB5.js.map +1 -0
- package/dist/components/{p-BFcukOp8.js → p-BLXc1FjC.js} +3 -3
- package/dist/components/{p-BFcukOp8.js.map → p-BLXc1FjC.js.map} +1 -1
- package/dist/components/{p-DXg4w3Tg.js → p-BcV6HHN8.js} +3 -3
- package/dist/components/{p-DXg4w3Tg.js.map → p-BcV6HHN8.js.map} +1 -1
- package/dist/components/{p-D3zeTcOR.js → p-DMkbzkL_.js} +3 -3
- package/dist/components/{p-D3zeTcOR.js.map → p-DMkbzkL_.js.map} +1 -1
- package/dist/components/{p-C6-nmq3h.js → p-DbJfa2yQ.js} +4 -4
- package/dist/components/{p-C6-nmq3h.js.map → p-DbJfa2yQ.js.map} +1 -1
- package/dist/components/{p-C8b9lX1K.js → p-ao6bHDbv.js} +34 -34
- package/dist/components/{p-C8b9lX1K.js.map → p-ao6bHDbv.js.map} +1 -1
- package/dist/components/{p-Cp6mvZCj.js → p-r9wMCtI3.js} +8 -8
- package/dist/components/{p-Cp6mvZCj.js.map → p-r9wMCtI3.js.map} +1 -1
- package/dist/components/polygon-buttons.js +1 -1
- package/dist/components/polygon-information.js +1 -1
- package/dist/components/settings-modal.js +1 -1
- package/dist/components/solar-calculator.js +1 -1
- package/dist/components/solar-expert.js +15 -12
- package/dist/components/solar-expert.js.map +1 -1
- package/dist/components/solar-system-form.js +1 -1
- package/dist/components/tool-box.js +1 -1
- package/dist/esm/eraser-icon.house-icon.icon-selector.map-draw.map-selector.move-icon.octagon-minus-icon.polygon-buttons.polygon-information.search-icon.settings-icon.settings-modal.solar-expert.solar-system-form.tool-box.undo-icon.entry.js.map +1 -1
- package/dist/esm/eraser-icon_16.entry.js +47 -45
- package/dist/esm/eraser-icon_16.entry.js.map +1 -1
- package/dist/esm/{index-DNOniOEj.js → index-yVbXII2Q.js} +28 -5
- package/dist/esm/index-yVbXII2Q.js.map +1 -0
- package/dist/esm/loader.js +3 -3
- package/dist/esm/loading-widget.entry.js +2 -2
- package/dist/esm/solar-calculator.entry.js +2 -2
- package/dist/esm/stencil-library.js +3 -3
- package/dist/stencil-library/eraser-icon.house-icon.icon-selector.map-draw.map-selector.move-icon.octagon-minus-icon.polygon-buttons.polygon-information.search-icon.settings-icon.settings-modal.solar-expert.solar-system-form.tool-box.undo-icon.entry.esm.js.map +1 -1
- package/dist/stencil-library/p-141320bb.entry.js +2 -0
- package/dist/stencil-library/p-141320bb.entry.js.map +1 -0
- package/dist/stencil-library/{p-4020a1f0.entry.js → p-2a83d5d6.entry.js} +3 -3
- package/dist/stencil-library/{p-76ce6493.entry.js → p-825501e2.entry.js} +2 -2
- package/dist/stencil-library/p-yVbXII2Q.js +3 -0
- package/dist/stencil-library/p-yVbXII2Q.js.map +1 -0
- package/dist/stencil-library/stencil-library.esm.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/index-C3Kp1xqq.js.map +0 -1
- package/dist/components/p-DRZd44KM.js.map +0 -1
- package/dist/esm/index-DNOniOEj.js.map +0 -1
- package/dist/stencil-library/p-8b5f9a3a.entry.js +0 -2
- package/dist/stencil-library/p-8b5f9a3a.entry.js.map +0 -1
- package/dist/stencil-library/p-DNOniOEj.js +0 -3
- package/dist/stencil-library/p-DNOniOEj.js.map +0 -1
- /package/dist/stencil-library/{p-4020a1f0.entry.js.map → p-2a83d5d6.entry.js.map} +0 -0
- /package/dist/stencil-library/{p-76ce6493.entry.js.map → p-825501e2.entry.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"file":"p-Cp6mvZCj.js","mappings":"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","names":["__stencil_proxyCustomElement","HTMLElement","uuidv4"],"sources":["src/utils/visualize.ts","src/utils/render/projection.ts","src/utils/render/polygon.ts","src/utils/render/color.ts","../../node_modules/uuid/dist/esm-browser/stringify.js","../../node_modules/uuid/dist/esm-browser/rng.js","../../node_modules/uuid/dist/esm-browser/native.js","../../node_modules/uuid/dist/esm-browser/v4.js","src/utils/geometry/fitting.ts","src/utils/geometry/gridMatch.ts","src/output.css?tag=map-draw","src/components/map-draw/map-draw.tsx"],"sourcesContent":["/*\r\n Copyright 2023 Google LLC\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n https://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n */\r\n\r\n import { PositionedSolarPanel } from './geometry/fitting';\r\nimport type { Bounds, GeoTiff, InternalSolarPanelConfig } from './solar';\r\n\r\n // [START visualize_render_rgb]\r\n /**\r\n * Renders an RGB GeoTiff image into an HTML canvas.\r\n *\r\n * The GeoTiff image must include 3 rasters (bands) which\r\n * correspond to [Red, Green, Blue] in that order.\r\n *\r\n * @param {GeoTiff} rgb GeoTiff with RGB values of the image.\r\n * @param {GeoTiff} mask Optional mask for transparency, defaults to opaque.\r\n * @return {HTMLCanvasElement} Canvas element with the rendered image.\r\n */\r\n export function renderRGB(rgb: GeoTiff, mask?: GeoTiff, canvas?: HTMLCanvasElement | null): HTMLCanvasElement {\r\n // Create an HTML canvas to draw the image.\r\n // https://www.w3schools.com/tags/canvas_createimagedata.asp\r\n if (!canvas) {\r\n canvas = document.createElement('canvas');\r\n }\r\n \r\n // Set the canvas size to the mask size if it's available,\r\n // otherwise set it to the RGB data layer size.\r\n canvas.width = mask ? mask.width : rgb.width;\r\n canvas.height = mask ? mask.height : rgb.height;\r\n \r\n // Since the mask size can be different than the RGB data layer size,\r\n // we calculate the \"delta\" between the RGB layer size and the canvas/mask\r\n // size. For example, if the RGB layer size is the same as the canvas size,\r\n // the delta is 1. If the RGB layer size is smaller than the canvas size,\r\n // the delta would be greater than 1.\r\n // This is used to translate the index from the canvas to the RGB layer.\r\n const dw = rgb.width / canvas.width;\r\n const dh = rgb.height / canvas.height;\r\n \r\n // Get the canvas image data buffer.\r\n const ctx = canvas.getContext('2d')!;\r\n const img = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n \r\n // Fill in every pixel in the canvas with the corresponding RGB layer value.\r\n // Since Javascript doesn't support multidimensional arrays or tensors,\r\n // everything is stored in flat arrays and we have to keep track of the\r\n // indices for each row and column ourselves.\r\n for (let y = 0; y < canvas.height; y++) {\r\n for (let x = 0; x < canvas.width; x++) {\r\n // RGB index keeps track of the RGB layer position.\r\n // This is multiplied by the deltas since it might be a different\r\n // size than the image size.\r\n const rgbIdx = Math.floor(y * dh) * rgb.width + Math.floor(x * dw);\r\n // Mask index keeps track of the mask layer position.\r\n const maskIdx = y * canvas.width + x;\r\n \r\n // Image index keeps track of the canvas image position.\r\n // HTML canvas expects a flat array with consecutive RGBA values.\r\n // Each value in the image buffer must be between 0 and 255.\r\n // The Alpha value is the transparency of that pixel,\r\n // if a mask was not provided, we default to 255 which is opaque.\r\n const imgIdx = y * canvas.width * 4 + x * 4;\r\n const factor = 0.8;\r\n img.data[imgIdx + 0] = Math.round(rgb.rasters[0][rgbIdx] * factor); // Red\r\n img.data[imgIdx + 1] = Math.round(rgb.rasters[1][rgbIdx] * factor); // Green\r\n img.data[imgIdx + 2] = Math.round(rgb.rasters[2][rgbIdx] * factor); // Blue\r\n img.data[imgIdx + 3] = mask // Alpha\r\n ? mask.rasters[0][maskIdx] * 255\r\n : 255;\r\n }\r\n }\r\n \r\n // Draw the image data buffer into the canvas context.\r\n ctx.putImageData(img, 0, 0);\r\n return canvas;\r\n }\r\n // [END visualize_render_rgb]\r\n \r\n // [START visualize_render_palette]\r\n /**\r\n * Renders a single value GeoTiff image into an HTML canvas.\r\n *\r\n * The GeoTiff image must include 1 raster (band) which contains\r\n * the values we want to display.\r\n *\r\n * @param {GeoTiff} data GeoTiff with the values of interest.\r\n * @param {GeoTiff} mask Optional mask for transparency, defaults to opaque.\r\n * @param {string[]} colors Hex color palette, defaults to ['000000', 'ffffff'].\r\n * @param {number} min Minimum value of the data range, defaults to 0.\r\n * @param {number} max Maximum value of the data range, defaults to 1.\r\n * @param {number} index Raster index for the data, defaults to 0.\r\n * @return {HTMLCanvasElement} Canvas element with the rendered image.\r\n */\r\n export function renderPalette({\r\n data,\r\n mask,\r\n colors,\r\n min,\r\n max,\r\n index,\r\n canvas,\r\n }: {\r\n data: GeoTiff;\r\n mask?: GeoTiff;\r\n colors?: string[];\r\n min?: number;\r\n max?: number;\r\n index?: number;\r\n canvas?: HTMLCanvasElement | null\t;\r\n }): HTMLCanvasElement {\r\n // First create a palette from a list of hex colors.\r\n const palette = createPalette(colors ?? ['000000', 'ffffff']);\r\n // Normalize each value of our raster/band of interest into indices,\r\n // such that they always map into a value within the palette.\r\n const indices = data.rasters[index ?? 0]\r\n .map((x) => normalize(x, max ?? 1, min ?? 0))\r\n .map((x) => Math.round(x * (palette.length - 1)));\r\n return renderRGB(\r\n {\r\n ...data,\r\n // Map each index into the corresponding RGB values.\r\n rasters: [\r\n indices.map((i: number) => palette[i].r),\r\n indices.map((i: number) => palette[i].g),\r\n indices.map((i: number) => palette[i].b),\r\n ],\r\n },\r\n mask,\r\n canvas,\r\n );\r\n }\r\n \r\n /**\r\n * Creates an {r, g, b} color palette from a hex list of colors.\r\n *\r\n * Each {r, g, b} value is a number between 0 and 255.\r\n * The created palette is always of size 256, regardless of the number of\r\n * hex colors passed in. Inbetween values are interpolated.\r\n *\r\n * @param {string[]} hexColors List of hex colors for the palette.\r\n * @return {{r, g, b}[]} RGB values for the color palette.\r\n */\r\n export function createPalette(hexColors: string[]): { r: number; g: number; b: number }[] {\r\n // Map each hex color into an RGB value.\r\n const rgb = hexColors.map(colorToRGB);\r\n // Create a palette with 256 colors derived from our rgb colors.\r\n const size = 256;\r\n const step = (rgb.length - 1) / (size - 1);\r\n return Array(size)\r\n .fill(0)\r\n .map((_, i) => {\r\n // Get the lower and upper indices for each color.\r\n const index = i * step;\r\n const lower = Math.floor(index);\r\n const upper = Math.ceil(index);\r\n // Interpolate between the colors to get the shades.\r\n return {\r\n r: lerp(rgb[lower].r, rgb[upper].r, index - lower),\r\n g: lerp(rgb[lower].g, rgb[upper].g, index - lower),\r\n b: lerp(rgb[lower].b, rgb[upper].b, index - lower),\r\n };\r\n });\r\n }\r\n \r\n /**\r\n * Convert a hex color into an {r, g, b} color.\r\n *\r\n * @param {string} color Hex color like 0099FF or #0099FF.\r\n * @return {{r, g, b}} RGB values for that color.\r\n */\r\n export function colorToRGB(color: string): { r: number; g: number; b: number } {\r\n const hex = color.startsWith('#') ? color.slice(1) : color;\r\n return {\r\n r: parseInt(hex.substring(0, 2), 16),\r\n g: parseInt(hex.substring(2, 4), 16),\r\n b: parseInt(hex.substring(4, 6), 16),\r\n };\r\n }\r\n \r\n /**\r\n * Normalizes a number to a given data range.\r\n *\r\n * @param {number} x Value of interest.\r\n * @param {number} max Maximum value in data range, defaults to 1.\r\n * @param {number} min Minimum value in data range, defaults to 0.\r\n * @return {number} Normalized value.\r\n */\r\n export function normalize(x: number, max: number = 1, min: number = 0): number {\r\n const y = (x - min) / (max - min);\r\n return clamp(y, 0, 1);\r\n }\r\n \r\n /**\r\n * Calculates the linear interpolation for a value within a range.\r\n *\r\n * @param {number} x Lower value in the range, when `t` is 0.\r\n * @param {number} y Upper value in the range, when `t` is 1.\r\n * @param {number} t \"Time\" between 0 and 1.\r\n * @return {number} Inbetween value for that \"time\".\r\n */\r\n export function lerp(x: number, y: number, t: number): number {\r\n return x + t * (y - x);\r\n }\r\n \r\n /**\r\n * Clamps a value to always be within a range.\r\n *\r\n * @param {number} x Value to clamp.\r\n * @param {number} min Minimum value in the range.\r\n * @param {number} max Maximum value in the range.\r\n * @return {number} Clamped value.\r\n */\r\n export function clamp(x: number, min: number, max: number): number {\r\n return Math.min(Math.max(x, min), max);\r\n }\r\n // [END visualize_render_palette]\r\n \r\n export function rgbToColor({ r, g, b }: { r: number; g: number; b: number }): string {\r\n const f = (x: number) => {\r\n const hex = Math.round(x).toString(16);\r\n return hex.length == 1 ? `0${hex}` : hex;\r\n };\r\n return `#${f(r)}${f(g)}${f(b)}`;\r\n }\r\n\r\n export function renderAzimuth(azimuth: number, ctx: CanvasRenderingContext2D) {\r\n if (azimuth === undefined) {\r\n return;\r\n }\r\n ctx.save();\r\n ctx.moveTo(0, 0);\r\n ctx.rotate((azimuth - 90) * Math.PI / 180);\r\n ctx.translate(ctx.canvas.width-100, 100);\r\n \r\n // Set arrow style\r\n ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';\r\n ctx.lineWidth = 2;\r\n\r\n ctx.moveTo(-50, 0);\r\n ctx.lineTo(50,0);\r\n ctx.lineTo(40,-10);\r\n ctx.moveTo(50,0);\r\n ctx.lineTo(40,10);\r\n ctx.stroke();\r\n\r\n ctx.moveTo(0, 0);\r\n ctx.beginPath();\r\n ctx.arc(0, 0, 50, 0, Math.PI * 2);\r\n ctx.stroke();\r\n\r\n // Arrow parameters\r\n // const arrowLength = 100;\r\n // const arrowHeadLength = 15;\r\n // const arrowHeadAngle = Math.PI / 6; // 30 degrees\r\n\r\n // // Convert azimuth to radians (subtract 90 degrees to align with standard compass)\r\n // const angle = (azimuth - 90) * Math.PI / 180;\r\n\r\n // // Calculate arrow end point\r\n // const endX = arrowLength * Math.cos(angle);\r\n // const endY = arrowLength * Math.sin(angle);\r\n\r\n // // Draw main arrow line\r\n // ctx.beginPath();\r\n // ctx.moveTo(0, 0);\r\n // ctx.lineTo(endX, endY);\r\n // ctx.stroke();\r\n\r\n // // Calculate arrowhead points\r\n // const arrowHeadAngle1 = angle + Math.PI - arrowHeadAngle;\r\n // const arrowHeadAngle2 = angle + Math.PI + arrowHeadAngle;\r\n\r\n // const arrowHead1X = endX + arrowHeadLength * Math.cos(arrowHeadAngle1);\r\n // const arrowHead1Y = endY + arrowHeadLength * Math.sin(arrowHeadAngle1);\r\n // const arrowHead2X = endX + arrowHeadLength * Math.cos(arrowHeadAngle2);\r\n // const arrowHead2Y = endY + arrowHeadLength * Math.sin(arrowHeadAngle2);\r\n\r\n // // Draw arrowhead\r\n // ctx.beginPath();\r\n // ctx.moveTo(endX, endY);\r\n // ctx.lineTo(arrowHead1X, arrowHead1Y);\r\n // ctx.lineTo(arrowHead2X, arrowHead2Y);\r\n // ctx.closePath();\r\n // ctx.fill();\r\n\r\n // ctx.translate(ctx.canvas.width/2, 50);\r\n\r\n ctx.restore();\r\n\r\n console.log(\"renderAzimuth\", azimuth);\r\n }\r\n\r\n export function renderSolarPanel(solarPanel: PositionedSolarPanel, ctx: CanvasRenderingContext2D, panelWidth: number, panelHeight: number, azimuthAngle: number, pitchAngle: number) {\r\n const { x, y } = solarPanel.pixelPosition;\r\n let width = panelWidth;\r\n let height = panelHeight * Math.cos(pitchAngle * Math.PI / 180);\r\n if (solarPanel.horizontal) {\r\n width = panelHeight;\r\n height = panelWidth * Math.cos(pitchAngle * Math.PI / 180);\r\n }\r\n\r\n // Save the current context state\r\n ctx.save();\r\n \r\n // Translate to the panel's center point\r\n ctx.translate(x, y);\r\n \r\n // Rotate by the azimuth angle (convert to radians)\r\n ctx.rotate((azimuthAngle * Math.PI) / 180);\r\n \r\n // Draw panel rectangle centered at origin (since we translated)\r\n ctx.fillStyle = 'rgba(0, 51, 204, 0.8)';\r\n ctx.fillRect(-width/2, -height/2, width, height);\r\n \r\n // Draw panel border\r\n ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';\r\n ctx.lineWidth = 1;\r\n ctx.strokeRect(-width/2, -height/2, width, height);\r\n \r\n // Restore the context state\r\n ctx.restore();\r\n}\r\n\r\n export function renderPanels({canvas, panelConfig, bounds, zoom, roofSegments}: \r\n {canvas: HTMLCanvasElement | null, panelConfig: InternalSolarPanelConfig, bounds: Bounds, zoom: number, roofSegments: Record<number, { pitchDegrees: number; azimuthDegrees: number }>}): HTMLCanvasElement {\r\n if (!canvas) {\r\n canvas = document.createElement('canvas');\r\n }\r\n \r\n const ctx = canvas.getContext(\"2d\")!;\r\n\r\n // Calculate pre zoomed dimensions the canvas is already zoomed\r\n const preZoomedWidth = Math.floor(canvas.width / zoom);\r\n const preZoomedHeight = Math.floor(canvas.height / zoom);\r\n const startX = Math.floor((preZoomedWidth - canvas.width) / 2);\r\n const startY = Math.floor((preZoomedHeight - canvas.height) / 2);\r\n\r\n // Calculate the scale factors to convert lat/lng to pixel coordinates\r\n const latToPixel = (lat: number) => {\r\n return preZoomedHeight * (1 - (lat - bounds.south) / (bounds.north - bounds.south)) - startY;\r\n };\r\n \r\n const lngToPixel = (lng: number) => {\r\n return preZoomedWidth * (lng - bounds.west) / (bounds.east - bounds.west) - startX;\r\n };\r\n \r\n // Draw each panel\r\n for (const panel of panelConfig.panels) {\r\n // Convert panel center coordinates to pixel coordinates\r\n const centerX = lngToPixel(panel.center.longitude);\r\n const centerY = latToPixel(panel.center.latitude);\r\n \r\n // Calculate panel dimensions (assuming standard panel size)\r\n const panelWidth = panel.orientation === 'LANDSCAPE' ? 19 : 10; // pixels\r\n const panelHeight = panel.orientation === 'LANDSCAPE' ? 10 : 19;\r\n \r\n // Get the roof segment's azimuth angle for this panel\r\n const roofSegment = roofSegments[panel.segmentIndex];\r\n const azimuthAngle = roofSegment ? roofSegment.azimuthDegrees : 0;\r\n \r\n // Save the current context state\r\n ctx.save();\r\n \r\n // Translate to the panel's center point\r\n ctx.translate(centerX, centerY);\r\n \r\n // Rotate by the azimuth angle (convert to radians)\r\n ctx.rotate((azimuthAngle * Math.PI) / 180);\r\n \r\n // Draw panel rectangle centered at origin (since we translated)\r\n ctx.fillStyle = 'rgba(115, 143, 255, 1)';\r\n ctx.fillRect(-panelWidth/2, -panelHeight/2, panelWidth, panelHeight);\r\n \r\n // Draw panel border\r\n ctx.strokeStyle = 'rgba(0, 0, 0, 0.8)';\r\n ctx.lineWidth = 1;\r\n ctx.strokeRect(-panelWidth/2, -panelHeight/2, panelWidth, panelHeight);\r\n \r\n // Restore the context state\r\n ctx.restore();\r\n }\r\n \r\n return canvas;\r\n }\r\n \r\n export function renderCombinedWithZoom({\r\n rgb,\r\n zoom = 1,\r\n canvas,\r\n}: {\r\n rgb: GeoTiff;\r\n zoom?: number;\r\n canvas?: HTMLCanvasElement | null;\r\n}): HTMLCanvasElement {\r\n // First render the RGB image\r\n const rgbCanvas = renderRGB(rgb, undefined, canvas);\r\n const ctx = rgbCanvas.getContext(\"2d\")!;\r\n const imgData = ctx.getImageData(0, 0, rgbCanvas.width, rgbCanvas.height);\r\n\r\n // Calculate the center portion to show based on zoom\r\n const width = rgbCanvas.width;\r\n const height = rgbCanvas.height;\r\n const zoomedWidth = Math.floor(width * zoom);\r\n const zoomedHeight = Math.floor(height * zoom);\r\n const startX = Math.floor((width - zoomedWidth) / 2);\r\n const startY = Math.floor((height - zoomedHeight) / 2);\r\n\r\n // Create a new image data for the zoomed portion\r\n const zoomedImgData = new ImageData(zoomedWidth, zoomedHeight);\r\n \r\n // Copy RGB data and apply palette where mask is non-zero\r\n for (let y = 0; y < height; y++) {\r\n for (let x = 0; x < width; x++) {\r\n const i = (y * width + x) * 4;\r\n \r\n if (x >= startX && x < startX + zoomedWidth && \r\n y >= startY && y < startY + zoomedHeight) {\r\n // Calculate position in zoomed image\r\n const zoomedX = x - startX;\r\n const zoomedY = y - startY;\r\n const zoomedI = (zoomedY * zoomedWidth + zoomedX) * 4;\r\n \r\n zoomedImgData.data[zoomedI] = imgData.data[i];\r\n zoomedImgData.data[zoomedI + 1] = imgData.data[i + 1];\r\n zoomedImgData.data[zoomedI + 2] = imgData.data[i + 2];\r\n zoomedImgData.data[zoomedI + 3] = 255; // Alpha channel\r\n }\r\n }\r\n }\r\n\r\n // Resize canvas to match zoomed dimensions\r\n rgbCanvas.width = zoomedWidth;\r\n rgbCanvas.height = zoomedHeight;\r\n \r\n // Put the zoomed image data back to the canvas\r\n ctx.putImageData(zoomedImgData, 0, 0);\r\n return rgbCanvas;\r\n}\r\n ","import { Point } from \"../../types/shapes\";\r\n\r\nexport function projectPointPerpendicularToLine({\r\n x,\r\n y,\r\n lastPoint,\r\n secondLastPoint,\r\n}: {\r\n x: number;\r\n y: number;\r\n lastPoint: { x: number; y: number };\r\n secondLastPoint: { x: number; y: number };\r\n}): Point {\r\n\r\n // Calculate the direction vector of the last line\r\n const dx = lastPoint.x - secondLastPoint.x;\r\n const dy = lastPoint.y - secondLastPoint.y;\r\n\r\n // Calculate perpendicular vector (rotate 90 degrees)\r\n const perpDx = -dy;\r\n const perpDy = dx;\r\n\r\n // Normalize the perpendicular vector\r\n const perpLength = Math.sqrt(perpDx * perpDx + perpDy * perpDy);\r\n const normalizedPerpDx = perpDx / perpLength;\r\n const normalizedPerpDy = perpDy / perpLength;\r\n\r\n // Project the mouse point onto the perpendicular line\r\n const vectorToMouse = {\r\n x: x - lastPoint.x,\r\n y: y - lastPoint.y,\r\n };\r\n\r\n // Calculate the projection length (dot product)\r\n const projectionLength = vectorToMouse.x * normalizedPerpDx +\r\n vectorToMouse.y * normalizedPerpDy;\r\n\r\n // Calculate the new point position using the projected length\r\n x = lastPoint.x + normalizedPerpDx * projectionLength;\r\n y = lastPoint.y + normalizedPerpDy * projectionLength;\r\n return { x, y };\r\n}\r\n","import { DOTTED_LINE_COLOR } from \"../../constants\";\r\nimport { Point, Polygon } from \"../../types/shapes\";\r\nimport { projectPointPerpendicularToLine } from \"./projection\";\r\n\r\nexport interface DrawPolygonProps {\r\n polygonCtx: CanvasRenderingContext2D;\r\n polygonCanvas: HTMLCanvasElement;\r\n polygon: Polygon;\r\n pixelInMeters: number;\r\n shiftKeyPressed: boolean;\r\n mousePoint: Point | null;\r\n strokeColor: string;\r\n highlightColor: string;\r\n fillColor?: string;\r\n highlightedEdge?: { pointA: Point; pointB: Point } | null;\r\n}\r\n\r\nexport interface Line{\r\n start: Point;\r\n end: Point;\r\n}\r\n\r\nexport interface DrawCircleProps {\r\n ctx: CanvasRenderingContext2D;\r\n x: number;\r\n y: number;\r\n radius: number;\r\n strokeStyle?: string;\r\n lineWidth?: number;\r\n}\r\n\r\nexport function drawPolygon({\r\n polygonCtx, polygonCanvas, polygon, shiftKeyPressed, mousePoint, strokeColor, fillColor, highlightedEdge, highlightColor\r\n}: DrawPolygonProps) {\r\n if (!polygonCtx || !polygonCanvas) return;\r\n\r\n // Draw the polygon\r\n polygonCtx.beginPath();\r\n polygonCtx.strokeStyle = strokeColor;\r\n polygonCtx.lineWidth = 2;\r\n\r\n polygon.points.forEach((point, index) => {\r\n if (index === 0) {\r\n polygonCtx.moveTo(point.x, point.y);\r\n } else {\r\n polygonCtx.lineTo(point.x, point.y);\r\n }\r\n });\r\n\r\n if (polygon.closed) {\r\n polygonCtx.lineTo(polygon.points[0].x, polygon.points[0].y);\r\n if (fillColor) {\r\n polygonCtx.fillStyle = fillColor;\r\n polygonCtx.fill();\r\n }\r\n }\r\n\r\n if (polygon.points.length > 0) {\r\n polygonCtx.stroke();\r\n }\r\n\r\n if (highlightedEdge && polygon.closed) {\r\n polygonCtx.beginPath();\r\n polygonCtx.strokeStyle = highlightColor;\r\n polygonCtx.lineWidth = 2;\r\n polygonCtx.moveTo(highlightedEdge.pointA.x, highlightedEdge.pointA.y);\r\n polygonCtx.lineTo(highlightedEdge.pointB.x, highlightedEdge.pointB.y);\r\n polygonCtx.stroke();\r\n polygonCtx.strokeStyle = strokeColor;\r\n polygonCtx.lineWidth = 1;\r\n }\r\n\r\n if (polygon.points.length > 1 && !polygon.closed && shiftKeyPressed) {\r\n const projectedPoint = projectPointPerpendicularToLine({\r\n x: mousePoint.x,\r\n y: mousePoint.y,\r\n lastPoint: polygon.points[polygon.points.length - 1],\r\n secondLastPoint: polygon.points[polygon.points.length - 2],\r\n });\r\n drawPerpendicularDottedLine({\r\n ctx: polygonCtx,\r\n startPoint: projectedPoint,\r\n endPoint: polygon.points[polygon.points.length - 1],\r\n strokeStyle: DOTTED_LINE_COLOR,\r\n });\r\n }\r\n\r\n if (shiftKeyPressed && polygon.points.length > 1 && !polygon.closed) {\r\n const projectedPoint = projectPointPerpendicularToLine({\r\n x: mousePoint.x,\r\n y: mousePoint.y,\r\n lastPoint: polygon.points[polygon.points.length - 1],\r\n secondLastPoint: polygon.points[polygon.points.length - 2],\r\n });\r\n drawCircle({\r\n ctx: polygonCtx,\r\n x: projectedPoint.x,\r\n y: projectedPoint.y,\r\n radius: 5,\r\n strokeStyle: DOTTED_LINE_COLOR,\r\n });\r\n }\r\n\r\n // Draw circles around each point\r\n polygon.points.forEach((point) => {\r\n polygonCtx.beginPath();\r\n const strokeStyle = strokeColor;\r\n const distance = Math.sqrt(\r\n Math.pow(point.x - mousePoint.x, 2) + Math.pow(point.y - mousePoint.y, 2)\r\n );\r\n\r\n // Highlight the point if it's being hovered or dragged\r\n if (\r\n distance < 10\r\n ) {\r\n drawCircle({\r\n ctx: polygonCtx,\r\n x: point.x,\r\n y: point.y,\r\n strokeStyle,\r\n radius: 8,\r\n });\r\n } else {\r\n drawCircle({\r\n ctx: polygonCtx,\r\n x: point.x,\r\n y: point.y,\r\n strokeStyle,\r\n radius: 5,\r\n });\r\n }\r\n\r\n polygonCtx.stroke();\r\n });\r\n}\r\n\r\nexport function drawCircle({\r\n ctx,\r\n x,\r\n y,\r\n radius,\r\n strokeStyle = \"black\",\r\n lineWidth = 2\r\n}: DrawCircleProps) {\r\n ctx.beginPath();\r\n ctx.strokeStyle = strokeStyle;\r\n ctx.lineWidth = lineWidth;\r\n \r\n ctx.arc(x, y, radius, 0, 2 * Math.PI);\r\n ctx.stroke();\r\n}\r\n\r\nexport function drawPerpendicularDottedLine({\r\n ctx,\r\n startPoint,\r\n endPoint,\r\n dashPattern = [5, 5],\r\n strokeStyle = \"black\",\r\n lineWidth = 2\r\n}: {\r\n ctx: CanvasRenderingContext2D;\r\n startPoint: Point;\r\n endPoint: Point;\r\n dashPattern?: number[];\r\n strokeStyle?: string;\r\n lineWidth?: number;\r\n}) {\r\n // Set up the line style\r\n ctx.beginPath();\r\n ctx.strokeStyle = strokeStyle;\r\n ctx.lineWidth = lineWidth;\r\n ctx.setLineDash(dashPattern);\r\n \r\n // Draw the dotted line\r\n ctx.moveTo(startPoint.x, startPoint.y);\r\n ctx.lineTo(endPoint.x, endPoint.y);\r\n ctx.stroke();\r\n \r\n // Reset the line dash\r\n ctx.setLineDash([]);\r\n}\r\n\r\nexport function isPointOnBorder(point: Point, polygon: Polygon): boolean {\r\n if (!polygon.closed || polygon.points.length < 3) return false;\r\n\r\n const x = point.x;\r\n const y = point.y;\r\n\r\n // For each edge of the polygon\r\n for (let i = 0; i < polygon.points.length; i++) {\r\n const p1 = polygon.points[i];\r\n const p2 = polygon.points[(i + 1) % polygon.points.length];\r\n // calculate the distance from point p1 to p2\r\n const distance = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\r\n const distanceToPoint = Math.sqrt(Math.pow(p1.x - x, 2) + Math.pow(p1.y - y, 2));\r\n const distanceFromPoint = Math.sqrt(Math.pow(p2.x - x, 2) + Math.pow(p2.y - y, 2));\r\n if (distance === distanceToPoint + distanceFromPoint) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function isPointInPolygon(point: Point, polygon: Polygon): boolean {\r\n if (!polygon.closed || polygon.points.length < 3) return false;\r\n\r\n const num_vertices = polygon.points.length;\r\n const x = point.x;\r\n const y = point.y;\r\n let inside = false;\r\n\r\n let p1 = polygon.points[0];\r\n let p2: Point;\r\n\r\n for (let i = 1; i <= num_vertices; i++) {\r\n p2 = polygon.points[i % num_vertices];\r\n\r\n if (y > Math.min(p1.y, p2.y)) {\r\n if (y <= Math.max(p1.y, p2.y)) {\r\n if (x <= Math.max(p1.x, p2.x)) {\r\n const x_intersection = ((y - p1.y) * (p2.x - p1.x)) / (p2.y - p1.y) + p1.x;\r\n\r\n if (p1.x === p2.x || x <= x_intersection) {\r\n inside = !inside;\r\n }\r\n }\r\n }\r\n }\r\n\r\n p1 = p2;\r\n }\r\n\r\n return inside;\r\n}","import { Polygon, SelectedPolygon } from \"../../types/shapes\";\r\nimport { SolarExpertConfig } from \"../../config\";\r\n\r\n\r\nexport function getFillColor(selectedPolygon: SelectedPolygon | null, hoveredPolygon: SelectedPolygon | null, _id: string, polygon: Polygon, config: SolarExpertConfig): string | undefined {\r\n const isHovered = hoveredPolygon?.type === polygon.type && hoveredPolygon?._id === _id;\r\n if (isHovered) {\r\n return polygon.type === \"roof\" ? config.roofPolygonHoverFillColor : config.obstructionPolygonHoverFillColor;\r\n }\r\n \r\n const isSelected = selectedPolygon?.type === polygon.type && selectedPolygon?._id === _id;\r\n\r\n if (isSelected) {\r\n return polygon.type === \"roof\" ? config.roofPolygonSelectedFillColor : config.obstructionPolygonSelectedFillColor;\r\n }\r\n\r\n if (polygon.type === \"roof\") {\r\n return polygon.closed ? config.roofPolygonFillColor : undefined;\r\n }\r\n return polygon.closed ? config.obstructionPolygonFillColor : undefined;\r\n}\r\n","import validate from './validate.js';\n\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nvar byteToHex = [];\nfor (var i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n //\n // Note to future-self: No, you can't remove the `toLowerCase()` call.\n // REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351\n return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n var uuid = unsafeStringify(arr, offset);\n // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;","// Unique ID creation requires a high quality random # generator. In the browser we therefore\n// require the crypto API and do not support built-in fallback to lower quality random number\n// generators (like Math.random()).\n\nvar getRandomValues;\nvar rnds8 = new Uint8Array(16);\nexport default function rng() {\n // lazy load so that environments that need to polyfill have a chance to do so\n if (!getRandomValues) {\n // getRandomValues needs to be invoked in a context where \"this\" is a Crypto implementation.\n getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);\n if (!getRandomValues) {\n throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n }\n }\n return getRandomValues(rnds8);\n}","var randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nexport default {\n randomUUID\n};","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n var rnds = options.random || (options.rng || rng)();\n\n // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80;\n\n // Copy bytes to buffer, if provided\n if (buf) {\n offset = offset || 0;\n for (var i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;","import { LineSegment, Polygon, SegmentMatch } from \"../../types/shapes\";\r\nimport { Bounds, LatLng, RoofSegmentSizeAndSunshineStats, SolarPanelType } from \"../solar\";\r\nimport { latLngToPixel } from \"../utils\";\r\nimport { Point } from \"../../types/shapes\";\r\nimport { isPointInPolygon, isPointOnBorder, Line } from \"../render/polygon\";\r\n\r\n\r\nexport interface SolarPanelSystemPart {\r\n positionedPanels: PositionedSolarPanel[];\r\n sunniness: number;\r\n}\r\n\r\nexport interface PositionedSolarPanel {\r\n panel: SolarPanelType;\r\n pixelPosition: {\r\n x: number;\r\n y: number;\r\n };\r\n horizontal: boolean;\r\n}\r\n\r\n/**\r\n * Get the intersections of a line parallel to the x-axis of the projected coordinate system with a polygon.\r\n * @param projectedPoint the point to draw the line from\r\n * @param projectedPolygon the polygon to get the intersections with\r\n * @returns the intersections of the line with the polygon\r\n */\r\nexport function getIntersections(projectedPoint: Point, projectedPolygon: Polygon): Point[] {\r\n const intersections: Point[] = [];\r\n\r\n if (projectedPolygon.points.length === 0) {\r\n return intersections;\r\n }\r\n \r\n // For each edge of the polygon\r\n for (let i = 0; i < projectedPolygon.points.length; i++) {\r\n const p1 = projectedPolygon.points[i];\r\n const p2 = projectedPolygon.points[(i + 1) % projectedPolygon.points.length];\r\n \r\n // Calculate intersection point\r\n const t = (projectedPoint.y - p1.y) / (p2.y - p1.y);\r\n const x = p1.x + t * (p2.x - p1.x);\r\n \r\n if (t > 0 && t <= 1) {\r\n intersections.push({ x, y: projectedPoint.y });\r\n }\r\n if (t === 0) {\r\n intersections.push({ x: p1.x, y: projectedPoint.y });\r\n }\r\n }\r\n \r\n // Sort intersections by y-coordinate\r\n return intersections.sort((a, b) => a.x - b.x);\r\n}\r\n\r\nexport function projectPoint(point: Point, azimuth: number): Point {\r\n const angle = azimuth * (Math.PI / 180);\r\n const x = point.x * Math.cos(angle) - point.y * Math.sin(angle);\r\n const y = point.x * Math.sin(angle) + point.y * Math.cos(angle);\r\n return { x, y };\r\n}\r\n\r\nexport function projectPolygon(polygon: Polygon, azimuth: number): Polygon {\r\n return {\r\n points: polygon.points.map((point) => projectPoint(point, azimuth)),\r\n type: polygon.type,\r\n closed: polygon.closed,\r\n _id: polygon._id,\r\n details: polygon.details,\r\n };\r\n}\r\n\r\nexport function offsetPolygon(polygon: Polygon, offset?: {x: number, y: number}): {polygon: Polygon, offset: {x: number, y: number}} {\r\n if (polygon.points.length === 0) {\r\n return { polygon: polygon, offset: {x: 0, y: 0} };\r\n }\r\n\r\n let offsetX = 0;\r\n let offsetY = 0;\r\n if (!offset) {\r\n const minX = Math.min(...polygon.points.map((point) => point.x));\r\n const minY = Math.min(...polygon.points.map((point) => point.y));\r\n const maxX = Math.max(...polygon.points.map((point) => point.x));\r\n const maxY = Math.max(...polygon.points.map((point) => point.y));\r\n\r\n offsetX = minX + (maxX - minX) / 2;\r\n offsetY = minY + (maxY - minY) / 2;\r\n }\r\n else {\r\n offsetX = offset.x;\r\n offsetY = offset.y;\r\n }\r\n\r\n const newPoints = polygon.points.map((point) => ({\r\n x: point.x - offsetX,\r\n y: point.y - offsetY,\r\n }));\r\n\r\n return { polygon: { ...polygon, points: newPoints }, offset: {x: offsetX, y: offsetY} };\r\n}\r\n\r\nfunction equalsPoints(point1: Point, point2: Point): boolean {\r\n return point1.x === point2.x && point1.y === point2.y;\r\n}\r\n\r\n/**\r\n * Checks if two lines intersect.\r\n * if the lines intersect in a start or end point they are not considered as intersecting\r\n * @param line1 The first line.\r\n * @param line2 The second line.\r\n * @returns True if the lines intersect, false otherwise.\r\n */\r\nexport function intersects(line1: Line, line2: Line): boolean {\r\n // Get the points of each line\r\n const p1 = line1.start;\r\n const p2 = line1.end;\r\n const p3 = line2.start;\r\n const p4 = line2.end;\r\n\r\n if (equalsPoints(p1, p3) || equalsPoints(p1, p4) || equalsPoints(p2, p3) || equalsPoints(p2, p4)) {\r\n return false;\r\n }\r\n\r\n // Calculate the cross products\r\n const d1 = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);\r\n const d2 = (p4.x - p3.x) * (p2.y - p3.y) - (p4.y - p3.y) * (p2.x - p3.x);\r\n const d3 = (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);\r\n const d4 = (p2.x - p1.x) * (p4.y - p1.y) - (p2.y - p1.y) * (p4.x - p1.x);\r\n\r\n // Check if the lines intersect\r\n return (d1 * d2 < 0) && (d3 * d4 < 0);\r\n}\r\n\r\nexport function undoOffsetPolygon(polygon: Polygon, offset: {x: number, y: number}): Polygon {\r\n return {\r\n ...polygon,\r\n points: polygon.points.map((point) => ({\r\n x: point.x + offset.x,\r\n y: point.y + offset.y,\r\n })),\r\n };\r\n}\r\n\r\nexport function segmentPolygon(polygon: Polygon) {\r\n const segments: LineSegment[] = [];\r\n const segmentsMap: Record<string, boolean> = {};\r\n\r\n for (const point of polygon.points) {\r\n const intersections = getIntersections(point, polygon);\r\n for (const [index, intersection] of intersections.slice(0, -1).entries()) {\r\n const nextIntersection = intersections[index + 1];\r\n \r\n const halfPoint = {\r\n x: (intersection.x + nextIntersection.x) / 2,\r\n y: (intersection.y + nextIntersection.y) / 2,\r\n };\r\n\r\n const isInner = isPointInPolygon(halfPoint, polygon);\r\n const isOnBorder = isPointOnBorder(halfPoint, polygon);\r\n const key = `${intersection.x}-${intersection.y}-${nextIntersection.x}-${nextIntersection.y}`;\r\n \r\n if (segmentsMap[key]) {\r\n continue;\r\n }\r\n segments.push({ start: intersection, end: nextIntersection, type: isOnBorder ? \"border\" : (isInner ? \"inner\" : \"outer\") });\r\n segmentsMap[key] = true;\r\n }\r\n }\r\n return segments;\r\n}\r\n\r\n/**\r\n * for each segment this method will find all the following segments that are connected to it\r\n * \r\n * first the method subdivides the segments into y levels (all segments that have the same y coordinate are in the same level)\r\n * then it will check for each segment in each level if there is a following segment that is connected to it by checking it the \r\n * start point of the top segment to the end point of the bottom segment does not intersect with any of the polygon borders and the center point of the connection is in the polygon\r\n * \r\n * @param segments \r\n * @param roof \r\n * @returns \r\n */\r\nexport function matchSegments(segments: LineSegment[], roof: Polygon): {matches: SegmentMatch[], map: Record<string, LineSegment>} {\r\n const matches: SegmentMatch[] = [];\r\n const map: Record<string, LineSegment> = {};\r\n\r\n for (const segment of segments) {\r\n map[`${segment.start.x}-${segment.start.y}-${segment.end.x}-${segment.end.y}`] = segment;\r\n }\r\n \r\n // Group segments by y-coordinate (level)\r\n const levels: Record<number, LineSegment[]> = {};\r\n segments.forEach(segment => {\r\n const y = segment.start.y;\r\n if (!levels[y]) {\r\n levels[y] = [];\r\n }\r\n levels[y].push(segment);\r\n });\r\n\r\n // Sort levels by y-coordinate\r\n const sortedLevels = Object.keys(levels).map(Number).sort((a, b) => a - b);\r\n\r\n // For each level except the last one\r\n for (let i = 0; i < sortedLevels.length - 1; i++) {\r\n const currentLevel = levels[sortedLevels[i]];\r\n const nextLevel = levels[sortedLevels[i + 1]];\r\n\r\n // For each segment in current level\r\n for (const currentSegment of currentLevel) {\r\n if (currentSegment.type === \"outer\") {\r\n continue;\r\n }\r\n const matchedSegments: LineSegment[] = [];\r\n \r\n // For each segment in next level\r\n for (const nextSegment of nextLevel) {\r\n // Check if segments can be connected\r\n const connectionStart = currentSegment.start;\r\n const connectionEnd = nextSegment.end;\r\n\r\n let intersected = false;\r\n for (let i = 0; i < roof.points.length; i++) {\r\n const line = {\r\n start: roof.points[i],\r\n end: roof.points[(i + 1) % roof.points.length]\r\n };\r\n if (intersects(line, {start: connectionStart, end: connectionEnd})) {\r\n intersected = true;\r\n break;\r\n }\r\n }\r\n\r\n if (intersected) {\r\n continue;\r\n }\r\n\r\n // Check if center point of connection is inside polygon\r\n const centerPoint = {\r\n x: (connectionStart.x + connectionEnd.x) / 2,\r\n y: (connectionStart.y + connectionEnd.y) / 2\r\n };\r\n\r\n if (isPointInPolygon(centerPoint, roof)) {\r\n matchedSegments.push(nextSegment);\r\n }\r\n }\r\n\r\n if (matchedSegments.length > 0) {\r\n matches.push({\r\n segment: `${currentSegment.start.x}-${currentSegment.start.y}-${currentSegment.end.x}-${currentSegment.end.y}`,\r\n matchedSegments: matchedSegments.map(segment => `${segment.start.x}-${segment.start.y}-${segment.end.x}-${segment.end.y}`)\r\n });\r\n }\r\n }\r\n }\r\n\r\n return {matches, map};\r\n}\r\n\r\n\r\n/**\r\n * Uses the bounding box of the roof and the roof segment bounding boxes to find the best fitting roof segment.\r\n * @param roof the roof shape\r\n * @param roofSegmentStats the stats of the roof segments\r\n * @returns the best fitting roof segment\r\n */\r\nexport function getBestFittingRoofSegment(roof: Polygon, roofSegmentStats: RoofSegmentSizeAndSunshineStats[], bounds: Bounds, canvas: HTMLCanvasElement): RoofSegmentSizeAndSunshineStats {\r\n const polygonBounds = {\r\n minX: Math.min(...roof.points.map((p) => p.x)),\r\n maxX: Math.max(...roof.points.map((p) => p.x)),\r\n minY: Math.min(...roof.points.map((p) => p.y)),\r\n maxY: Math.max(...roof.points.map((p) => p.y)),\r\n };\r\n\r\n let bestSegment = null;\r\n let bestIoU = 0;\r\n\r\n for (const segment of roofSegmentStats) {\r\n const sw = latLngToPixel(bounds, canvas, {\r\n latitude: segment.boundingBox.sw.latitude,\r\n longitude: segment.boundingBox.sw.longitude,\r\n } as LatLng);\r\n const ne = latLngToPixel(bounds, canvas, {\r\n latitude: segment.boundingBox.ne.latitude,\r\n longitude: segment.boundingBox.ne.longitude,\r\n } as LatLng);\r\n const segmentBounds = {\r\n minX: sw.x,\r\n maxX: ne.x,\r\n minY: ne.y,\r\n maxY: sw.y,\r\n };\r\n\r\n // Calculate intersection\r\n const interLeft = Math.max(polygonBounds.minX, segmentBounds.minX);\r\n const interRight = Math.min(polygonBounds.maxX, segmentBounds.maxX);\r\n const interTop = Math.max(polygonBounds.minY, segmentBounds.minY);\r\n const interBottom = Math.min(polygonBounds.maxY, segmentBounds.maxY);\r\n\r\n const interWidth = interRight - interLeft;\r\n const interHeight = interBottom - interTop;\r\n let intersectionArea = 0;\r\n if (interWidth > 0 && interHeight > 0) {\r\n intersectionArea = interWidth * interHeight;\r\n }\r\n\r\n const polygonArea = (polygonBounds.maxX - polygonBounds.minX) * (polygonBounds.maxY - polygonBounds.minY);\r\n const segmentArea = (segmentBounds.maxX - segmentBounds.minX) * (segmentBounds.maxY - segmentBounds.minY);\r\n const unionArea = polygonArea + segmentArea - intersectionArea;\r\n const iou = unionArea > 0 ? intersectionArea / unionArea : 0;\r\n\r\n if (iou > bestIoU) {\r\n bestIoU = iou;\r\n bestSegment = segment;\r\n }\r\n }\r\n\r\n return bestSegment;\r\n}\r\n","import { COLUMN_SPACING, ROW_SPACING } from \"../../constants\";\r\nimport { Point, Polygon } from \"../../types/shapes\";\r\nimport { isPointInPolygon, Line } from \"../render/polygon\";\r\nimport { SolarPanelType } from \"../solar\";\r\nimport { intersects, offsetPolygon, PositionedSolarPanel, projectPoint, projectPolygon } from \"./fitting\";\r\n\r\nexport interface MinMax {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n}\r\n\r\nexport function generateGrid(minMax: MinMax, solarPanel: SolarPanelType, horizontal: boolean, anker: Point, rowSpacing: number, columnSpacing: number): Array<Array<PositionedSolarPanel>> {\r\n const grid: Array<Array<PositionedSolarPanel>> = [];\r\n const width = horizontal ? solarPanel.heightMeters : solarPanel.widthMeters;\r\n const widthCount = Math.ceil((minMax.maxX - minMax.minX) / width);\r\n const height = horizontal ? solarPanel.widthMeters : solarPanel.heightMeters;\r\n const heightCount = Math.ceil((minMax.maxY - minMax.minY) / height);\r\n\r\n const widthOffset = width / 2;\r\n const heightOffset = height / 2;\r\n\r\n // calculate the starting point based on the anker\r\n const startX = anker.x - (Math.ceil((anker.x - minMax.minX) / width) * width);\r\n const startY = anker.y - (Math.ceil((anker.y - minMax.minY) / height) * height);\r\n\r\n for (let i = 0; i < heightCount; i++) {\r\n const row: Array<PositionedSolarPanel> = [];\r\n for (let j = 0; j < widthCount; j++) {\r\n const x = startX + j * width + j * columnSpacing + widthOffset;\r\n const y = startY + i * height + i * rowSpacing + heightOffset;\r\n const positionedSolarPanel: PositionedSolarPanel = {\r\n panel: solarPanel,\r\n pixelPosition: {\r\n x: x,\r\n y: y\r\n },\r\n horizontal: horizontal\r\n }\r\n row.push(positionedSolarPanel);\r\n }\r\n grid.push(row);\r\n }\r\n return grid;\r\n}\r\n\r\nfunction getSolarPanelLines(positionedSolarPanel: PositionedSolarPanel, horizontal: boolean): Array<Line> {\r\n const width = horizontal ? positionedSolarPanel.panel.heightMeters : positionedSolarPanel.panel.widthMeters;\r\n const height = horizontal ? positionedSolarPanel.panel.widthMeters : positionedSolarPanel.panel.heightMeters;\r\n const p1 = {\r\n x: positionedSolarPanel.pixelPosition.x - width / 2,\r\n y: positionedSolarPanel.pixelPosition.y - height / 2\r\n }\r\n const p2 = {\r\n x: positionedSolarPanel.pixelPosition.x - width / 2,\r\n y: positionedSolarPanel.pixelPosition.y + height / 2\r\n }\r\n const p3 = {\r\n x: positionedSolarPanel.pixelPosition.x + width / 2,\r\n y: positionedSolarPanel.pixelPosition.y + height / 2\r\n }\r\n const p4 = {\r\n x: positionedSolarPanel.pixelPosition.x + width / 2,\r\n y: positionedSolarPanel.pixelPosition.y - height / 2\r\n }\r\n const lines = [\r\n {\r\n start: p1,\r\n end: p2\r\n },\r\n {\r\n start: p2,\r\n end: p3\r\n },\r\n {\r\n start: p3,\r\n end: p4\r\n },\r\n {\r\n start: p4,\r\n end: p1\r\n }\r\n ]\r\n return lines;\r\n}\r\n\r\n\r\nexport function solarPanelInObstacle(positionedSolarPanel: PositionedSolarPanel, obstacle: Polygon, horizontal: boolean): boolean {\r\n const lines = getSolarPanelLines(positionedSolarPanel, horizontal);\r\n if (isPointInPolygon(positionedSolarPanel.pixelPosition, obstacle)) {\r\n return true;\r\n }\r\n for (let i = 0; i < obstacle.points.length; i++) {\r\n const point = obstacle.points[i];\r\n const nextPoint = obstacle.points[(i + 1) % obstacle.points.length];\r\n const border = {\r\n start: point,\r\n end: nextPoint\r\n }\r\n for (const line of lines) {\r\n if (intersects(line, border)) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function solarPanelInPolygon(positionedSolarPanel: PositionedSolarPanel, polygon: Polygon, horizontal: boolean): boolean {\r\n const lines = getSolarPanelLines(positionedSolarPanel, horizontal);\r\n\r\n for (let i = 0; i < polygon.points.length; i++) {\r\n const point = polygon.points[i];\r\n const nextPoint = polygon.points[(i + 1) % polygon.points.length];\r\n const border = {\r\n start: point,\r\n end: nextPoint\r\n }\r\n for (const line of lines) {\r\n if (intersects(line, border)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return isPointInPolygon(positionedSolarPanel.pixelPosition, polygon);\r\n}\r\n\r\nexport interface Obstacle {\r\n polygon: Polygon;\r\n boundingBox: {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n }\r\n}\r\n\r\nexport function isPanelObstructed(positionedSolarPanel: PositionedSolarPanel, obstacles: Obstacle[], horizontal: boolean): boolean {\r\n for (const obstacle of obstacles) {\r\n if (solarPanelInObstacle(positionedSolarPanel, obstacle.polygon, horizontal)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function getSolarPanelsInPolygon(grid: Array<Array<PositionedSolarPanel>>, polygon: Polygon, horizontal: boolean, obstacles: Obstacle[]): Array<Array<PositionedSolarPanel>> {\r\n const solarPanels: Array<Array<PositionedSolarPanel>> = [];\r\n for (const row of grid) {\r\n let newRow: Array<PositionedSolarPanel> = [];\r\n for (const positionedSolarPanel of row) {\r\n const isObstructed = isPanelObstructed(positionedSolarPanel, obstacles, horizontal);\r\n if (solarPanelInPolygon(positionedSolarPanel, polygon, horizontal) && !isObstructed) {\r\n newRow.push(positionedSolarPanel);\r\n }\r\n }\r\n solarPanels.push(newRow);\r\n }\r\n return solarPanels;\r\n}\r\n\r\nexport function getOptimalSolarPosition(roof: Polygon, obstacles: Obstacle[], solarPanel: SolarPanelType, angle: number): Array<Array<PositionedSolarPanel>> {\r\n const minX = Math.min(...roof.points.map(p => p.x));\r\n const maxX = Math.max(...roof.points.map(p => p.x));\r\n const minY = Math.min(...roof.points.map(p => p.y));\r\n const maxY = Math.max(...roof.points.map(p => p.y));\r\n const minMax = {\r\n minX: minX,\r\n maxX: maxX,\r\n minY: minY,\r\n maxY: maxY\r\n } as MinMax; \r\n\r\n const horizontalSolarPanel = {\r\n ...solarPanel,\r\n widthMeters: solarPanel.widthMeters * Math.cos(angle * Math.PI / 180),\r\n heightMeters: solarPanel.heightMeters\r\n } as SolarPanelType;\r\n\r\n const verticalSolarPanel = {\r\n ...solarPanel,\r\n widthMeters: solarPanel.widthMeters,\r\n heightMeters: solarPanel.heightMeters * Math.cos(angle * Math.PI / 180)\r\n } as SolarPanelType;\r\n\r\n let solarPanels: Array<Array<PositionedSolarPanel>> = [];\r\n let numberOfPanels = 0;\r\n for (const point of roof.points) {\r\n for (const horizontal of [false]) { // TODO removed true\r\n const grid = generateGrid(minMax, horizontal ? horizontalSolarPanel : verticalSolarPanel, horizontal, point, ROW_SPACING, COLUMN_SPACING);\r\n const solarPanelsInPolygon = getSolarPanelsInPolygon(grid, roof, horizontal, obstacles);\r\n\r\n const numberOfPanelsInPolygon = solarPanelsInPolygon.reduce((acc, row) => acc + row.length, 0);\r\n if (numberOfPanelsInPolygon > numberOfPanels) {\r\n numberOfPanels = numberOfPanelsInPolygon;\r\n solarPanels = solarPanelsInPolygon;\r\n }\r\n }\r\n break;\r\n }\r\n return solarPanels;\r\n}\r\n\r\nfunction projectObstacles(obstacles: Polygon[], azimuth: number, offset: {x: number, y: number}, inset: number): Array<Obstacle> {\r\n const result: Array<Obstacle> = [];\r\n for (const obstacle of obstacles) {\r\n const offsetObstacle = offsetPolygon(obstacle, offset);\r\n const projectedObstacle = projectPolygon(offsetObstacle.polygon, -azimuth);\r\n const insetObstacle = insetPolygon(projectedObstacle, -inset);\r\n\r\n const minX = Math.min(...insetObstacle.points.map(p => p.x));\r\n const maxX = Math.max(...insetObstacle.points.map(p => p.x));\r\n const minY = Math.min(...insetObstacle.points.map(p => p.y));\r\n const maxY = Math.max(...insetObstacle.points.map(p => p.y));\r\n const boundingBox = {\r\n minX: minX,\r\n maxX: maxX,\r\n minY: minY,\r\n maxY: maxY\r\n } as MinMax;\r\n result.push({\r\n polygon: projectedObstacle,\r\n boundingBox: boundingBox\r\n });\r\n }\r\n return result;\r\n}\r\n\r\nfunction isClockwise(points: Point[]): boolean {\r\n let sum = 0;\r\n for (let i = 0; i < points.length; i++) {\r\n const curr = points[i];\r\n const next = points[(i + 1) % points.length];\r\n sum += (next.x - curr.x) * (next.y + curr.y);\r\n }\r\n return sum > 0;\r\n}\r\n\r\nexport function insetPolygon(polygon: Polygon, inset: number): Polygon {\r\n const points = polygon.points;\r\n const isClockwisePolygon = isClockwise(points);\r\n inset = inset * Math.sqrt(2) * (isClockwisePolygon ? -1 : 1);\r\n const insetPoints: Point[] = [];\r\n \r\n for (let i = 0; i < points.length; i++) {\r\n const prev = points[(i - 1 + points.length) % points.length];\r\n const curr = points[i];\r\n const next = points[(i + 1) % points.length];\r\n \r\n // Calculate vectors for the two edges meeting at current point\r\n const v1 = {\r\n x: curr.x - prev.x,\r\n y: curr.y - prev.y\r\n };\r\n const v2 = {\r\n x: next.x - curr.x,\r\n y: next.y - curr.y\r\n };\r\n \r\n // Calculate perpendicular vectors (90 degrees clockwise)\r\n const perp1 = {\r\n x: -v1.y,\r\n y: v1.x\r\n };\r\n const perp2 = {\r\n x: -v2.y,\r\n y: v2.x\r\n };\r\n \r\n // Normalize the perpendicular vectors\r\n const length1 = Math.sqrt(perp1.x * perp1.x + perp1.y * perp1.y);\r\n const length2 = Math.sqrt(perp2.x * perp2.x + perp2.y * perp2.y);\r\n \r\n perp1.x /= length1;\r\n perp1.y /= length1;\r\n perp2.x /= length2;\r\n perp2.y /= length2;\r\n \r\n // Calculate the bisector vector\r\n const bisector = {\r\n x: perp1.x + perp2.x,\r\n y: perp1.y + perp2.y\r\n };\r\n \r\n // Normalize the bisector\r\n const bisectorLength = Math.sqrt(bisector.x * bisector.x + bisector.y * bisector.y);\r\n bisector.x /= bisectorLength;\r\n bisector.y /= bisectorLength;\r\n \r\n // Calculate the inset point\r\n const insetPoint = {\r\n x: curr.x + bisector.x * inset,\r\n y: curr.y + bisector.y * inset\r\n };\r\n \r\n insetPoints.push(insetPoint);\r\n }\r\n \r\n return {\r\n points: insetPoints,\r\n type: polygon.type,\r\n closed: polygon.closed,\r\n _id: polygon._id,\r\n details: polygon.details\r\n };\r\n}\r\n\r\nexport function getOptimalSolarPositionFully(roof: Polygon, obstacles: Polygon[], solarPanel: SolarPanelType, azimuth: number, inset: number, angle: number): Array<PositionedSolarPanel> {\r\n const insetRoof = insetPolygon(roof, inset);\r\n const offset = offsetPolygon(insetRoof);\r\n const projectedOffset = projectPolygon(offset.polygon, -azimuth);\r\n\r\n const projectedObstacles = projectObstacles(obstacles, azimuth, offset.offset, inset);\r\n\r\n const horizontalSolarPanels = getOptimalSolarPosition(projectedOffset, projectedObstacles, solarPanel, angle);\r\n const unprojectedPanels: Array<PositionedSolarPanel> = [];\r\n\r\n for (const panel of horizontalSolarPanels.flat()) {\r\n const unprojectedPanel = projectPoint(panel.pixelPosition, azimuth);\r\n const offsetPosition = {\r\n x: unprojectedPanel.x + offset.offset.x,\r\n y: unprojectedPanel.y + offset.offset.y\r\n }\r\n unprojectedPanels.push({\r\n panel: panel.panel,\r\n pixelPosition: offsetPosition,\r\n horizontal: panel.horizontal\r\n });\r\n }\r\n return unprojectedPanels;\r\n}","/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-800: oklch(27.8% 0.033 256.848);\n --color-black: #000;\n --spacing: 0.25rem;\n --container-md: 28rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --radius-lg: 0.5rem;\n --radius-4xl: 2rem;\n --animate-spin: spin 1s linear infinite;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n --color-primary: hsl(41 51% 90%);\n --color-primary-foreground: hsl(0 0% 0%);\n --color-secondary: hsl(28 100% 8%);\n --color-secondary-foreground: hsl(0 0% 100%);\n --color-tertiary: hsl(28 100% 29%);\n --color-tertiary-foreground: hsl(0 0% 100%);\n --color-muted: hsl(0 0% 100%);\n --color-muted-foreground: hsl(0 0% 0%);\n --color-error: hsl(0 100% 50%);\n --color-error-foreground: hsl(0 0% 100%);\n --color-surface: hsl(0 0% 88%);\n --color-surface-hover: hsl(0 0% 82%);\n --color-surface-active: hsl(0 0% 64%);\n --color-text-muted: hsl(0 0% 45%);\n --color-text-secondary: hsl(0 0% 55%);\n --color-text-placeholder: hsl(0 0% 73%);\n --color-border: hsl(0 0% 82%);\n --color-border-light: hsl(0 0% 93%);\n --color-success: hsl(142 76% 36%);\n --color-info: hsl(221 83% 53%);\n --color-hover: hsl(0 0% 88%);\n --color-hover-dark: hsl(28 100% 8%);\n --color-overlay: rgba(0, 0, 0, 0.24);\n --color-tooltip: hsl(0 0% 13%);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=\"until-found\"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-none {\n pointer-events: none;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-3 {\n left: calc(var(--spacing) * 3);\n }\n .z-20 {\n z-index: 20;\n }\n .z-50 {\n z-index: 50;\n }\n .m-auto {\n margin: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-4 {\n margin-top: calc(var(--spacing) * 4);\n }\n .mt-6 {\n margin-top: calc(var(--spacing) * 6);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .block {\n display: block;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .inline-flex {\n display: inline-flex;\n }\n .h-4 {\n height: calc(var(--spacing) * 4);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-16 {\n height: calc(var(--spacing) * 16);\n }\n .h-48 {\n height: calc(var(--spacing) * 48);\n }\n .h-\\[400px\\] {\n height: 400px;\n }\n .h-full {\n height: 100%;\n }\n .w-4 {\n width: calc(var(--spacing) * 4);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-16 {\n width: calc(var(--spacing) * 16);\n }\n .w-64 {\n width: calc(var(--spacing) * 64);\n }\n .w-full {\n width: 100%;\n }\n .max-w-md {\n max-width: var(--container-md);\n }\n .flex-1 {\n flex: 1;\n }\n .flex-3 {\n flex: 3;\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-help {\n cursor: help;\n }\n .appearance-none {\n appearance: none;\n }\n .grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n .grid-rows-2 {\n grid-template-rows: repeat(2, minmax(0, 1fr));\n }\n .grid-rows-3 {\n grid-template-rows: repeat(3, minmax(0, 1fr));\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-row {\n flex-direction: row;\n }\n .flex-wrap {\n flex-wrap: wrap;\n }\n .items-center {\n align-items: center;\n }\n .items-start {\n align-items: flex-start;\n }\n .items-stretch {\n align-items: stretch;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .justify-start {\n justify-content: flex-start;\n }\n .gap-0 {\n gap: calc(var(--spacing) * 0);\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .space-y-4 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-6 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-4xl {\n border-radius: var(--radius-4xl);\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t-2 {\n border-top-style: var(--tw-border-style);\n border-top-width: 2px;\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-border {\n border-color: var(--color-border);\n }\n .border-error {\n border-color: var(--color-error);\n }\n .border-gray-300 {\n border-color: var(--color-gray-300);\n }\n .border-secondary {\n border-color: var(--color-secondary);\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-gray-800 {\n background-color: var(--color-gray-800);\n }\n .bg-muted {\n background-color: var(--color-muted);\n }\n .bg-overlay {\n background-color: var(--color-overlay);\n }\n .bg-primary {\n background-color: var(--color-primary);\n }\n .bg-secondary {\n background-color: var(--color-secondary);\n }\n .bg-surface {\n background-color: var(--color-surface);\n }\n .bg-surface-active {\n background-color: var(--color-surface-active);\n }\n .bg-text-secondary {\n background-color: var(--color-text-secondary);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .p-1 {\n padding: calc(var(--spacing) * 1);\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-3 {\n padding: calc(var(--spacing) * 3);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .pt-2 {\n padding-top: calc(var(--spacing) * 2);\n }\n .pt-4 {\n padding-top: calc(var(--spacing) * 4);\n }\n .pt-7 {\n padding-top: calc(var(--spacing) * 7);\n }\n .pr-4 {\n padding-right: calc(var(--spacing) * 4);\n }\n .pb-3 {\n padding-bottom: calc(var(--spacing) * 3);\n }\n .pb-4 {\n padding-bottom: calc(var(--spacing) * 4);\n }\n .pl-2 {\n padding-left: calc(var(--spacing) * 2);\n }\n .pl-4 {\n padding-left: calc(var(--spacing) * 4);\n }\n .pl-10 {\n padding-left: calc(var(--spacing) * 10);\n }\n .text-center {\n text-align: center;\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .text-error {\n color: var(--color-error);\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-muted {\n color: var(--color-muted);\n }\n .text-muted-foreground {\n color: var(--color-muted-foreground);\n }\n .text-primary-foreground {\n color: var(--color-primary-foreground);\n }\n .text-secondary {\n color: var(--color-secondary);\n }\n .text-secondary-foreground {\n color: var(--color-secondary-foreground);\n }\n .text-success {\n color: var(--color-success);\n }\n .text-text-muted {\n color: var(--color-text-muted);\n }\n .text-text-placeholder {\n color: var(--color-text-placeholder);\n }\n .text-text-secondary {\n color: var(--color-text-secondary);\n }\n .accent-tertiary {\n accent-color: var(--color-tertiary);\n }\n .opacity-0 {\n opacity: 0%;\n }\n .shadow {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .group-hover\\:opacity-100 {\n &:is(:where(.group):hover *) {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n }\n .hover\\:bg-hover {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-hover);\n }\n }\n }\n .hover\\:bg-hover-dark {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-hover-dark);\n }\n }\n }\n .hover\\:bg-muted {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-muted);\n }\n }\n }\n .hover\\:bg-overlay {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-overlay);\n }\n }\n }\n .hover\\:bg-secondary {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-secondary);\n }\n }\n }\n .hover\\:bg-secondary\\/80 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, hsl(28 100% 8%) 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-secondary) 80%, transparent);\n }\n }\n }\n }\n .hover\\:bg-surface-hover {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-surface-hover);\n }\n }\n }\n .hover\\:bg-tertiary {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-tertiary);\n }\n }\n }\n .hover\\:bg-text-secondary {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-text-secondary);\n }\n }\n }\n .hover\\:text-muted {\n &:hover {\n @media (hover: hover) {\n color: var(--color-muted);\n }\n }\n }\n .focus\\:border-transparent {\n &:focus {\n border-color: transparent;\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-info {\n &:focus {\n --tw-ring-color: var(--color-info);\n }\n }\n .focus\\:ring-secondary {\n &:focus {\n --tw-ring-color: var(--color-secondary);\n }\n }\n .focus\\:ring-tertiary {\n &:focus {\n --tw-ring-color: var(--color-tertiary);\n }\n }\n .focus\\:ring-offset-0 {\n &:focus {\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .lg\\:gap-4 {\n @media (width >= 64rem) {\n gap: calc(var(--spacing) * 4);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:rounded-full {\n &::-webkit-slider-runnable-track {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:bg-black\\/25 {\n &::-webkit-slider-runnable-track {\n background-color: color-mix(in srgb, #000 25%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 25%, transparent);\n }\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:h-\\[10px\\] {\n &::-webkit-slider-thumb {\n height: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:w-\\[10px\\] {\n &::-webkit-slider-thumb {\n width: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:appearance-none {\n &::-webkit-slider-thumb {\n appearance: none;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:rounded-full {\n &::-webkit-slider-thumb {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:bg-muted {\n &::-webkit-slider-thumb {\n background-color: var(--color-muted);\n }\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-space-y-reverse {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-space-y-reverse: 0;\n --tw-border-style: solid;\n --tw-font-weight: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-duration: initial;\n }\n }\n}\n","import {\r\n Component,\r\n Element,\r\n h,\r\n Listen,\r\n Prop,\r\n State,\r\n Watch,\r\n} from \"@stencil/core\";\r\n\r\nimport {\r\n renderCombinedWithZoom,\r\n renderSolarPanel,\r\n} from \"../../utils/visualize\";\r\nimport {\r\n BuildingInsightsResponse,\r\n GeoTiff,\r\n SolarPanelType,\r\n} from \"../../utils/solar\";\r\nimport { fetchSolarData, getBuildingImages } from \"../../utils/api\";\r\nimport { drawPolygon, isPointInPolygon } from \"../../utils/render/polygon\";\r\nimport { projectPointPerpendicularToLine } from \"../../utils/render/projection\";\r\nimport { Point, Polygon, SelectedPolygon } from \"../../types/shapes\";\r\nimport {\r\n deleteTool,\r\n markRoofEdgeTool,\r\n moveTool,\r\n obstructionTool,\r\n roofTool,\r\n Tool,\r\n tools,\r\n} from \"../../utils/render/tools\";\r\nimport {\r\n DEFAULT_SOLAR_EXPERT_CONFIG,\r\n DEFAULT_SOLAR_PANEL_TYPE,\r\n SolarExpertConfig,\r\n} from \"../../config\";\r\nimport { getFillColor } from \"../../utils/render/color\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\nimport { calculatePolygonArea, getPixelInMeters } from \"../../utils/utils\";\r\nimport {\r\n getBestFittingRoofSegment,\r\n SolarPanelSystemPart,\r\n} from \"../../utils/geometry/fitting\";\r\nimport { getOptimalSolarPositionFully } from \"../../utils/geometry/gridMatch\";\r\nimport { BORDER_INSET, DEFAULT_SUNNINESS } from \"../../constants\";\r\nimport { getLanguageStrings } from \"../../utils/lang/general\";\r\nimport { onChange, Settings, state } from \"../../store\";\r\n\r\n@Component({\r\n tag: \"map-draw\",\r\n styleUrl: \"../../output.css\",\r\n shadow: false,\r\n})\r\nexport class MapDraw {\r\n @Prop()\r\n apiKey: string = \"\";\r\n @Prop()\r\n config: SolarExpertConfig = DEFAULT_SOLAR_EXPERT_CONFIG;\r\n @Prop()\r\n solarPanel: SolarPanelType = DEFAULT_SOLAR_PANEL_TYPE;\r\n\r\n @State()\r\n showInstructions: boolean = true;\r\n @State()\r\n showSettings: boolean = false;\r\n @State()\r\n zoom: number = 1;\r\n @State()\r\n loadingState: \"empty\" | \"loading\" | \"loaded\" = \"empty\";\r\n @State()\r\n rgbTiff: GeoTiff | null = null;\r\n @State()\r\n draggedPointIndex: number | null = null;\r\n @State()\r\n hoveredPointIndex: number | null = null;\r\n @State()\r\n hoveredPolygon: SelectedPolygon | null = null;\r\n @State()\r\n shiftKeyPressed: boolean = false;\r\n @State()\r\n altKeyPressed: boolean = false;\r\n @State()\r\n mousePoint: Point | null = null;\r\n @State()\r\n currentTool: Tool = roofTool;\r\n @State()\r\n roofPolygons: { [id: string]: Polygon } = {};\r\n @State()\r\n roofPolygonsSolarPanels: { [id: string]: SolarPanelSystemPart } = {};\r\n @State()\r\n obstructionPolygons: { [id: string]: Polygon } = {};\r\n @State()\r\n selectedPolygon: SelectedPolygon | null = null;\r\n @State()\r\n buildingInsights: BuildingInsightsResponse | null = null;\r\n @State()\r\n pixelInMeters: number = 0.2;\r\n @State()\r\n isMobile: boolean = false;\r\n @State()\r\n highlightedEdge: { pointA: Point; pointB: Point } | null = null;\r\n\r\n @Element()\r\n el: HTMLElement;\r\n private canvasElement?: HTMLCanvasElement;\r\n private polygonCanvas?: HTMLCanvasElement;\r\n private polygonCtx?: CanvasRenderingContext2D;\r\n\r\n private getCurrentPolygon(): Polygon | null {\r\n if (!this.selectedPolygon) {\r\n return null;\r\n }\r\n const { _id, type } = this.selectedPolygon;\r\n return type === \"roof\"\r\n ? this.roofPolygons[_id]\r\n : this.obstructionPolygons[_id];\r\n }\r\n\r\n componentWillLoad() {\r\n onChange(\"latitude\", () => {\r\n this.getBuildingImages();\r\n this.getBuildingInsights();\r\n });\r\n onChange(\"longitude\", () => {\r\n this.getBuildingImages();\r\n this.getBuildingInsights();\r\n });\r\n }\r\n\r\n componentDidLoad() {\r\n if (state.latitude && state.longitude) {\r\n this.loadingState = \"loading\";\r\n this.getBuildingInsights();\r\n this.getBuildingImages();\r\n }\r\n\r\n requestAnimationFrame(() => {\r\n if (this.canvasElement) {\r\n const rect = this.canvasElement.getBoundingClientRect();\r\n this.canvasElement.width = rect.width;\r\n this.canvasElement.height = rect.height;\r\n this.drawMap();\r\n }\r\n });\r\n }\r\n\r\n private sizeCanvas(width: number, height: number) {\r\n if (this.canvasElement) {\r\n this.canvasElement.width = width;\r\n this.canvasElement.height = height;\r\n }\r\n if (this.polygonCanvas) {\r\n this.polygonCanvas.width = width;\r\n this.polygonCanvas.height = height;\r\n this.polygonCtx = this.polygonCanvas.getContext(\"2d\");\r\n }\r\n }\r\n\r\n async getBuildingInsights() {\r\n if (!state.latitude || !state.longitude) {\r\n return;\r\n }\r\n this.loadingState = \"loading\";\r\n\r\n if (this.buildingInsights) {\r\n const sameLocation =\r\n this.buildingInsights.center.latitude === state.latitude &&\r\n this.buildingInsights.center.longitude === state.longitude;\r\n if (sameLocation) {\r\n return;\r\n }\r\n this.obstructionPolygons = {};\r\n this.roofPolygons = {};\r\n this.selectedPolygon = null;\r\n this.hoveredPolygon = null;\r\n this.canvasElement.getContext(\"2d\")?.clearRect(\r\n 0,\r\n 0,\r\n this.canvasElement.width,\r\n this.canvasElement.height,\r\n );\r\n this.polygonCtx?.clearRect(\r\n 0,\r\n 0,\r\n this.polygonCanvas.width,\r\n this.polygonCanvas.height,\r\n );\r\n this.rgbTiff = null;\r\n }\r\n this.buildingInsights = await fetchSolarData(\r\n state.latitude,\r\n state.longitude,\r\n this.apiKey,\r\n );\r\n if (!this.buildingInsights) {\r\n alert(\"No building insights found. Please enter them manually.\");\r\n }\r\n\r\n // If on mobile, automatically calculate panels using Google API data\r\n if (state.isMobile && this.buildingInsights) {\r\n const maxPanels =\r\n this.buildingInsights.solarPotential.maxArrayPanelsCount;\r\n const approximatedPanels = Math.floor(maxPanels * 3 / 4); // Use two thirds of max panels\r\n\r\n const positionedPanels = Array(approximatedPanels).fill(null)\r\n .map((_, __) => ({\r\n panel: this.solarPanel,\r\n pixelPosition: {\r\n x: -1,\r\n y: -1,\r\n },\r\n horizontal: true,\r\n rotation: 0,\r\n }));\r\n\r\n this.roofPolygonsSolarPanels = {\r\n ...this.roofPolygonsSolarPanels,\r\n [\"mobile-panels\"]: {\r\n positionedPanels,\r\n sunniness:\r\n this.buildingInsights.solarPotential.buildingStats\r\n .sunshineQuantiles[5] ?? DEFAULT_SUNNINESS,\r\n },\r\n };\r\n }\r\n }\r\n\r\n async getBuildingImages() {\r\n if (!state.latitude || !state.longitude) {\r\n return;\r\n }\r\n if (this.buildingInsights) {\r\n const sameLocation =\r\n this.buildingInsights.center.latitude === state.latitude &&\r\n this.buildingInsights.center.longitude === state.longitude;\r\n if (sameLocation) {\r\n return;\r\n }\r\n }\r\n this.rgbTiff = await getBuildingImages(\r\n state.latitude,\r\n state.longitude,\r\n this.apiKey,\r\n state.radiusMeters,\r\n );\r\n this.pixelInMeters = getPixelInMeters(this.rgbTiff);\r\n this.loadingState = \"loaded\";\r\n }\r\n\r\n private convertToCanvasCoordinates(event: MouseEvent): Point {\r\n const rect = this.polygonCanvas.getBoundingClientRect();\r\n const siteX = event.clientX - rect.left;\r\n const siteY = event.clientY - rect.top;\r\n return {\r\n x: siteX / (rect.right - rect.left) * this.canvasElement.width,\r\n y: siteY / (rect.bottom - rect.top) * this.canvasElement.height,\r\n };\r\n }\r\n\r\n @Watch(\"rgbTiff\")\r\n @Watch(\"buildingInsights\")\r\n @Watch(\"canvasElement\")\r\n async drawMap() {\r\n if (\r\n !this.canvasElement || !this.rgbTiff || !this.buildingInsights\r\n ) return;\r\n\r\n this.sizeCanvas(this.rgbTiff.width, this.rgbTiff.height);\r\n\r\n renderCombinedWithZoom({\r\n rgb: this.rgbTiff,\r\n zoom: this.zoom,\r\n canvas: this.canvasElement,\r\n });\r\n }\r\n\r\n @Listen(\"mousemove\", { target: \"document\" })\r\n handleMouseMove(event: MouseEvent) {\r\n if (state.isMobile) return; // Prevent interactions on mobile\r\n if (!this.polygonCanvas || !this.polygonCtx) return;\r\n\r\n // translate the website pixel coordinates to the canvas coordinates\r\n const { x, y } = this.convertToCanvasCoordinates(event);\r\n this.mousePoint = { x, y };\r\n\r\n const currentPolygon = this.getCurrentPolygon();\r\n let redraw = false;\r\n\r\n if (this.currentTool.name === \"markRoofEdge\") {\r\n let distances = [];\r\n for (let i = 0; i < currentPolygon?.points.length; i++) {\r\n const pointA = currentPolygon?.points[i];\r\n const pointB = currentPolygon\r\n ?.points[(i + 1) % currentPolygon?.points.length];\r\n const distanceA = Math.sqrt(\r\n Math.pow(x - pointA.x, 2) + Math.pow(y - pointA.y, 2),\r\n );\r\n const distanceB = Math.sqrt(\r\n Math.pow(x - pointB.x, 2) + Math.pow(y - pointB.y, 2),\r\n );\r\n const edgeLength = Math.sqrt(\r\n Math.pow(pointA.x - pointB.x, 2) +\r\n Math.pow(pointA.y - pointB.y, 2),\r\n );\r\n distances.push({\r\n dist: distanceA + distanceB - edgeLength,\r\n edge: { pointA, pointB },\r\n });\r\n }\r\n const closestEdge = distances.sort((a, b) => a.dist - b.dist)[0];\r\n if (closestEdge && (closestEdge.dist < 10)) {\r\n this.highlightedEdge = closestEdge.edge;\r\n redraw = true;\r\n } else if (this.highlightedEdge) {\r\n this.highlightedEdge = null;\r\n redraw = true;\r\n }\r\n }\r\n\r\n // Check for point hover\r\n const newHoveredPointIndex = currentPolygon?.points.findIndex(\r\n (point) => {\r\n const distance = Math.sqrt(\r\n Math.pow(x - point.x, 2) + Math.pow(y - point.y, 2),\r\n );\r\n return distance < 10;\r\n },\r\n );\r\n\r\n // Check for polygon hover\r\n let newHoveredPolygon = null;\r\n for (const polygon of Object.values(this.obstructionPolygons)) {\r\n if (isPointInPolygon({ x, y }, polygon)) {\r\n newHoveredPolygon = { _id: polygon._id, type: \"obstruction\" };\r\n break;\r\n }\r\n }\r\n // obstruction polygons get priority\r\n if (!newHoveredPolygon) {\r\n for (const polygon of Object.values(this.roofPolygons)) {\r\n if (isPointInPolygon({ x, y }, polygon)) {\r\n newHoveredPolygon = { _id: polygon._id, type: \"roof\" };\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // Only redraw if hover state changed\r\n if (\r\n this.hoveredPolygon ||\r\n newHoveredPointIndex !== this.hoveredPointIndex ||\r\n JSON.stringify(newHoveredPolygon) !==\r\n JSON.stringify(this.hoveredPolygon)\r\n ) {\r\n this.hoveredPointIndex = newHoveredPointIndex;\r\n this.hoveredPolygon = newHoveredPolygon;\r\n redraw = true;\r\n }\r\n\r\n // Handle dragging\r\n if (\r\n this.draggedPointIndex !== null && currentPolygon &&\r\n this.currentTool.name === \"move\"\r\n ) {\r\n currentPolygon.points[this.draggedPointIndex] = { x, y };\r\n // Recalculate area if this is a roof polygon\r\n if (currentPolygon.type === \"roof\" && currentPolygon.closed) {\r\n const metersInPixels = 1 / this.pixelInMeters;\r\n const area = calculatePolygonArea(currentPolygon.points) /\r\n (metersInPixels * metersInPixels);\r\n currentPolygon.details.area = area;\r\n }\r\n redraw = true;\r\n }\r\n\r\n if (this.shiftKeyPressed) {\r\n redraw = true;\r\n }\r\n\r\n if (redraw) {\r\n this.drawPolygons();\r\n }\r\n }\r\n\r\n private drawPolygons() {\r\n if (!this.polygonCanvas || !this.polygonCtx) return;\r\n\r\n // Clear the canvas and redraw the map\r\n this.polygonCtx.clearRect(\r\n 0,\r\n 0,\r\n this.polygonCanvas.width,\r\n this.polygonCanvas.height,\r\n );\r\n\r\n // draw roof polygons\r\n for (const polygon of Object.values(this.roofPolygons)) {\r\n const fillColor = getFillColor(\r\n this.selectedPolygon,\r\n this.hoveredPolygon,\r\n polygon._id,\r\n polygon,\r\n this.config,\r\n );\r\n\r\n drawPolygon({\r\n polygonCtx: this.polygonCtx,\r\n polygonCanvas: this.polygonCanvas,\r\n polygon,\r\n strokeColor: polygon.closed\r\n ? this.config.closedRoofColor\r\n : this.config.openRoofColor,\r\n fillColor,\r\n pixelInMeters: this.pixelInMeters,\r\n shiftKeyPressed: this.shiftKeyPressed,\r\n mousePoint: this.mousePoint,\r\n highlightColor: this.config.highlightColor,\r\n highlightedEdge: this.highlightedEdge,\r\n });\r\n\r\n const solarPanels = this.roofPolygonsSolarPanels[polygon._id];\r\n const convertedSolarPanel: SolarPanelType = {\r\n ...this.solarPanel,\r\n widthMeters: this.solarPanel.widthMeters / this.pixelInMeters,\r\n heightMeters: this.solarPanel.heightMeters / this.pixelInMeters,\r\n };\r\n if (solarPanels) {\r\n for (const panel of solarPanels.positionedPanels) {\r\n renderSolarPanel(\r\n panel,\r\n this.polygonCtx,\r\n convertedSolarPanel.widthMeters,\r\n convertedSolarPanel.heightMeters,\r\n polygon.details?.azimuth,\r\n polygon.details?.pitch,\r\n );\r\n }\r\n }\r\n }\r\n\r\n // draw obstruction polygons\r\n for (const polygon of Object.values(this.obstructionPolygons)) {\r\n const fillColor = getFillColor(\r\n this.selectedPolygon,\r\n this.hoveredPolygon,\r\n polygon._id,\r\n polygon,\r\n this.config,\r\n );\r\n\r\n drawPolygon({\r\n polygonCtx: this.polygonCtx,\r\n polygonCanvas: this.polygonCanvas,\r\n polygon,\r\n pixelInMeters: this.pixelInMeters,\r\n shiftKeyPressed: this.shiftKeyPressed,\r\n mousePoint: this.mousePoint,\r\n strokeColor: polygon.closed\r\n ? this.config.closedObstructionColor\r\n : this.config.openObstructionColor,\r\n fillColor,\r\n highlightColor: this.config.highlightColor,\r\n });\r\n }\r\n }\r\n\r\n private deletePolygon(_id: string) {\r\n if (this.selectedPolygon?._id === _id) {\r\n this.selectedPolygon = null;\r\n }\r\n if (this.roofPolygons[_id]) {\r\n delete this.roofPolygons[_id];\r\n delete this.roofPolygonsSolarPanels[_id];\r\n }\r\n if (this.obstructionPolygons[_id]) {\r\n delete this.obstructionPolygons[_id];\r\n }\r\n }\r\n\r\n @Listen(\"keydown\", { target: \"document\" })\r\n handleKeyDown(event: KeyboardEvent) {\r\n if (event.target instanceof HTMLInputElement) {\r\n return;\r\n }\r\n // Handle shift key for perpendicular points\r\n if (event.shiftKey && !this.shiftKeyPressed) {\r\n this.shiftKeyPressed = true;\r\n this.drawPolygons();\r\n return;\r\n }\r\n if (event.altKey && !this.altKeyPressed) {\r\n this.altKeyPressed = true;\r\n return;\r\n }\r\n if (\r\n (event.key === \"Delete\" || event.key === \"Backspace\") &&\r\n this.selectedPolygon\r\n ) {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (currentPolygon.closed) {\r\n this.deletePolygon(currentPolygon._id);\r\n this.drawPolygons();\r\n return;\r\n }\r\n currentPolygon.points.pop();\r\n this.drawPolygons();\r\n return;\r\n }\r\n\r\n // Handle tool selection shortcuts\r\n const pressedKey = event.key.toLowerCase();\r\n const tool = tools.find((t) =>\r\n t.keyboardShortcut?.toLowerCase() === pressedKey\r\n );\r\n if (tool) {\r\n this.currentTool = tool;\r\n }\r\n }\r\n\r\n @Listen(\"keyup\", { target: \"document\" })\r\n handleKeyUp(event: KeyboardEvent) {\r\n if (!event.shiftKey && this.shiftKeyPressed) {\r\n this.shiftKeyPressed = false;\r\n this.drawPolygons();\r\n }\r\n if (!event.altKey && this.altKeyPressed) {\r\n this.altKeyPressed = false;\r\n }\r\n }\r\n\r\n private undo() {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (!currentPolygon) {\r\n return;\r\n }\r\n if (currentPolygon.closed) {\r\n currentPolygon.closed = false;\r\n if (currentPolygon.type === \"roof\") {\r\n delete this.roofPolygonsSolarPanels[currentPolygon._id];\r\n this.currentTool = roofTool;\r\n this.highlightedEdge = null;\r\n } else if (currentPolygon.type === \"obstruction\") {\r\n this.currentTool = obstructionTool;\r\n }\r\n } else {\r\n currentPolygon.points.pop();\r\n }\r\n this.drawPolygons();\r\n }\r\n\r\n @Listen(\"mousedown\", { target: \"document\" })\r\n handleMouseDown(event: MouseEvent) {\r\n if (this.currentTool.name === \"undo\") {\r\n return;\r\n }\r\n if (state.isMobile) return; // Prevent interactions on mobile\r\n if (!this.polygonCanvas || !this.polygonCtx) return;\r\n if (!this.polygonCanvas.contains(event.target as Node)) return;\r\n\r\n let { x, y } = this.convertToCanvasCoordinates(event);\r\n\r\n if (this.currentTool.name === \"markRoofEdge\") {\r\n if (!this.highlightedEdge) {\r\n return;\r\n }\r\n const x = this.highlightedEdge.pointA.x -\r\n this.highlightedEdge.pointB.x;\r\n const y = this.highlightedEdge.pointA.y -\r\n this.highlightedEdge.pointB.y;\r\n const azimuth = Math.atan2(-x, y) * (180 / Math.PI);\r\n this.calculateSolarPanels();\r\n this.handleAzimuthChange({\r\n target: {\r\n value: azimuth,\r\n },\r\n } as unknown as Event);\r\n return;\r\n }\r\n if (this.currentTool.name === \"delete\") {\r\n if (!this.hoveredPolygon) {\r\n return;\r\n }\r\n const { _id, type } = this.hoveredPolygon;\r\n if (type === \"roof\") {\r\n delete this.roofPolygons[_id];\r\n delete this.roofPolygonsSolarPanels[_id];\r\n } else if (type === \"obstruction\") {\r\n delete this.obstructionPolygons[_id];\r\n }\r\n this.hoveredPolygon = null;\r\n if (this.selectedPolygon?._id === _id) {\r\n this.selectedPolygon = null;\r\n }\r\n this.drawPolygons();\r\n return;\r\n }\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (this.currentTool.name === \"move\") {\r\n // Check if we're clicking on a point of the selected polygon\r\n if (this.selectedPolygon) {\r\n const pointIndex = currentPolygon?.points.findIndex((point) => {\r\n const distance = Math.sqrt(\r\n Math.pow(x - point.x, 2) + Math.pow(y - point.y, 2),\r\n );\r\n return distance < 10;\r\n });\r\n if (pointIndex !== undefined && pointIndex !== -1) {\r\n this.draggedPointIndex = pointIndex;\r\n return;\r\n }\r\n\r\n if (this.hoveredPolygon) {\r\n this.selectedPolygon = this.hoveredPolygon;\r\n return;\r\n }\r\n }\r\n this.selectedPolygon = null;\r\n this.drawPolygons();\r\n return;\r\n }\r\n if (\r\n !this.selectedPolygon || currentPolygon?.closed ||\r\n this.currentTool.name !== this.selectedPolygon?.type\r\n ) {\r\n // no polygon is active, create a new one\r\n const newPolygon: Polygon = {\r\n _id: uuidv4(),\r\n points: [{ x, y }],\r\n type: this.currentTool.name,\r\n closed: false,\r\n };\r\n let _id;\r\n if (this.currentTool.name === \"roof\") {\r\n this.roofPolygons = {\r\n ...this.roofPolygons,\r\n [newPolygon._id]: newPolygon,\r\n };\r\n _id = newPolygon._id;\r\n } else if (this.currentTool.name === \"obstruction\") {\r\n this.obstructionPolygons = {\r\n ...this.obstructionPolygons,\r\n [newPolygon._id]: newPolygon,\r\n };\r\n _id = newPolygon._id;\r\n }\r\n this.selectedPolygon = { _id, type: this.currentTool.name };\r\n this.drawPolygons();\r\n return;\r\n }\r\n\r\n if (currentPolygon.closed) {\r\n return;\r\n }\r\n\r\n // If we have at least one point, check if we're clicking near the first point\r\n if (currentPolygon.points.length > 2) {\r\n const firstPoint = currentPolygon.points[0];\r\n const distance = Math.sqrt(\r\n Math.pow(x - firstPoint.x, 2) + Math.pow(y - firstPoint.y, 2),\r\n );\r\n\r\n if (distance < 10) {\r\n this.closePolygon();\r\n return;\r\n }\r\n }\r\n\r\n // Handle shift key for perpendicular points\r\n if (event.shiftKey && currentPolygon?.points.length >= 2) {\r\n const projectedPoint = projectPointPerpendicularToLine({\r\n x,\r\n y,\r\n lastPoint:\r\n currentPolygon.points[currentPolygon.points.length - 1],\r\n secondLastPoint:\r\n currentPolygon.points[currentPolygon.points.length - 2],\r\n });\r\n x = projectedPoint.x;\r\n y = projectedPoint.y;\r\n }\r\n\r\n currentPolygon.points = [...currentPolygon.points, { x, y }];\r\n this.drawPolygons();\r\n }\r\n\r\n @Listen(\"mouseup\", { target: \"document\" })\r\n handleMouseUp() {\r\n this.draggedPointIndex = null;\r\n }\r\n\r\n private closePolygon() {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (\r\n currentPolygon.points.length >= 3 &&\r\n (this.currentTool.name === \"roof\" ||\r\n this.currentTool.name === \"obstruction\")\r\n ) {\r\n currentPolygon.closed = true;\r\n }\r\n\r\n if (currentPolygon.type === \"roof\") {\r\n // Calculate basic polygon details\r\n const metersInPixels = 1 / this.pixelInMeters;\r\n const area = calculatePolygonArea(currentPolygon.points) /\r\n (metersInPixels * metersInPixels);\r\n const bestMatch = getBestFittingRoofSegment(\r\n currentPolygon,\r\n this.buildingInsights?.solarPotential.roofSegmentStats,\r\n this.rgbTiff.bounds,\r\n this.canvasElement,\r\n );\r\n\r\n if (bestMatch) {\r\n currentPolygon.details = {\r\n area,\r\n azimuth: bestMatch.azimuthDegrees,\r\n pitch: bestMatch.pitchDegrees,\r\n };\r\n } else {\r\n currentPolygon.details = {\r\n area,\r\n azimuth: 0,\r\n pitch: 0,\r\n };\r\n }\r\n\r\n this.scrollToCanvas();\r\n }\r\n\r\n this.drawPolygons();\r\n this.currentTool = moveTool;\r\n }\r\n\r\n private calculateSolarPanels({ redraw = true }: { redraw?: boolean } = {}) {\r\n const currentPolygon = this.getCurrentPolygon();\r\n\r\n if (!currentPolygon.details) {\r\n return;\r\n }\r\n\r\n if (this.roofPolygonsSolarPanels[currentPolygon._id]) {\r\n delete this.roofPolygonsSolarPanels[currentPolygon._id];\r\n }\r\n\r\n const convertedSolarPanel: SolarPanelType = {\r\n ...this.solarPanel,\r\n widthMeters: this.solarPanel.widthMeters / this.pixelInMeters,\r\n heightMeters: this.solarPanel.heightMeters / this.pixelInMeters,\r\n };\r\n const inset = BORDER_INSET / this.pixelInMeters;\r\n const solarPanels = getOptimalSolarPositionFully(\r\n currentPolygon,\r\n Object.values(this.obstructionPolygons),\r\n convertedSolarPanel,\r\n currentPolygon.details?.azimuth,\r\n inset,\r\n currentPolygon.details?.pitch,\r\n );\r\n this.roofPolygonsSolarPanels = {\r\n ...this.roofPolygonsSolarPanels,\r\n [currentPolygon._id]: {\r\n positionedPanels: solarPanels,\r\n sunniness: currentPolygon.details?.assignedRoofStats?.stats\r\n .sunshineQuantiles[5] ??\r\n this.buildingInsights.solarPotential.buildingStats\r\n .sunshineQuantiles[5] ??\r\n DEFAULT_SUNNINESS,\r\n },\r\n };\r\n if (redraw) {\r\n this.drawPolygons();\r\n }\r\n }\r\n\r\n private handlePitchChange(event: Event) {\r\n const target = event.target as HTMLInputElement;\r\n const pitch = parseFloat(target.value);\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (currentPolygon) {\r\n this.roofPolygons[currentPolygon._id].details.pitch = pitch;\r\n }\r\n if (\r\n currentPolygon.type === \"roof\" &&\r\n this.roofPolygonsSolarPanels[currentPolygon._id]\r\n ) {\r\n this.calculateSolarPanels();\r\n return;\r\n }\r\n }\r\n\r\n private handleAzimuthChange(event: Event) {\r\n const target = event.target as HTMLInputElement;\r\n const azimuth = parseFloat(target.value);\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (currentPolygon) {\r\n this.roofPolygons[currentPolygon._id].details.azimuth = azimuth;\r\n }\r\n if (\r\n currentPolygon.type === \"roof\" &&\r\n this.roofPolygonsSolarPanels[currentPolygon._id]\r\n ) {\r\n this.calculateSolarPanels();\r\n return;\r\n }\r\n }\r\n\r\n private handleToolSelect(tool: Tool) {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (\r\n currentPolygon && !currentPolygon.closed &&\r\n currentPolygon.points.length > 0\r\n ) {\r\n alert(\"Please close the polygon before selecting a tool\");\r\n // TODO translate\r\n return;\r\n }\r\n this.currentTool = tool;\r\n }\r\n\r\n private scrollToCanvas() {\r\n const canvasElement = this.el.querySelector(\"#map-draw-canvas\");\r\n if (canvasElement) {\r\n canvasElement.scrollIntoView({ behavior: \"smooth\" });\r\n }\r\n }\r\n\r\n private handleSettingsClick = () => {\r\n this.showSettings = true;\r\n };\r\n\r\n private handleSettingsClose = () => {\r\n this.showSettings = false;\r\n };\r\n\r\n private handleSettingsSave = (event: CustomEvent<Settings>) => {\r\n state.settings = event.detail;\r\n state.settingsVersion++;\r\n };\r\n\r\n render() {\r\n const t = getLanguageStrings(state.settings.language);\r\n const currentPolygon = this.getCurrentPolygon();\r\n return (\r\n <div\r\n class=\"flex flex-col justify-center items-center w-full h-full gap-4 bg-primary\"\r\n id=\"map-draw\"\r\n >\r\n {this.showInstructions && !state.isMobile && (\r\n <div class=\"w-full rounded-4xl p-4 bg-muted text-muted-foreground\">\r\n {t.mapDraw.instructions.parts.roof}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() => this.handleToolSelect(roofTool)}\r\n >\r\n <icon-selector name=\"house\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.obstruction}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() =>\r\n this.handleToolSelect(obstructionTool)}\r\n >\r\n <icon-selector name=\"octagon-minus\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.delete}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() => this.handleToolSelect(deleteTool)}\r\n >\r\n <icon-selector name=\"eraser\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.move}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() => this.handleToolSelect(moveTool)}\r\n >\r\n <icon-selector name=\"move\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.end}\r\n </div>\r\n )}\r\n <div class=\"w-full flex flex-row justify-between items-center\">\r\n {!state.isMobile && (this.showInstructions\r\n ? (\r\n <button\r\n class=\"px-4 py-2 rounded-4xl hover:bg-surface-hover transition-colors duration-200 bg-muted p-4 text-muted-foreground\"\r\n onClick={() => this.showInstructions = false}\r\n >\r\n {t.mapDraw.instructions.hide}\r\n </button>\r\n )\r\n : (\r\n <button\r\n class=\"px-4 py-2 rounded-4xl hover:bg-surface-hover transition-colors duration-200 bg-muted p-4 text-muted-foreground\"\r\n onClick={() => this.showInstructions = true}\r\n >\r\n {t.mapDraw.instructions.show}\r\n </button>\r\n ))}\r\n <button\r\n class=\"flex items-center gap-2 bg-muted p-2 rounded-4xl hover:bg-surface-hover text-muted-foreground\"\r\n onClick={this.handleSettingsClick}\r\n >\r\n <settings-icon />\r\n </button>\r\n </div>\r\n <div class=\"w-full\">\r\n {!state.isMobile && (\r\n <tool-box\r\n currentTool={this.currentTool}\r\n onToolSelect={(tool) => this.handleToolSelect(tool)}\r\n undoCallback={() => this.undo()}\r\n />\r\n )}\r\n </div>\r\n {this.loadingState === \"empty\" && (\r\n <div class=\"w-full\">\r\n <p class=\"text-muted text-center flex items-center justify-center rounded-4xl p-4 w-full bg-text-secondary\">\r\n {t.mapDraw.noAddressSelected}\r\n </p>\r\n </div>\r\n )}\r\n {(state.latitude && state.longitude &&\r\n this.loadingState === \"loading\") && (\r\n <div class=\"flex items-center justify-center w-full bg-opacity-75 z-20 pt-7 rounded-4xl\">\r\n <div class=\"animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-secondary\">\r\n </div>\r\n </div>\r\n )}\r\n <div class=\"flex items-start justify-center h-full w-full bg-primary rounded-4xl\">\r\n <div\r\n class=\"relative h-full flex items-center justify-center w-full rounded-4xl bg-secondary\"\r\n style={{\r\n aspectRatio: this.rgbTiff\r\n ? `${this.rgbTiff.width}/${this.rgbTiff.height}`\r\n : \"1/1\",\r\n }}\r\n >\r\n <canvas\r\n ref={(el) => this.canvasElement = el}\r\n class=\"absolute top-0 left-0 w-full h-full rounded-4xl\"\r\n id=\"map-draw-canvas\"\r\n style={{\r\n cursor: this.currentTool.cursor,\r\n }}\r\n >\r\n </canvas>\r\n <canvas\r\n ref={(el) => this.polygonCanvas = el}\r\n class=\"absolute top-0 left-0 w-full h-full rounded-4xl\"\r\n style={{\r\n cursor: this.currentTool.cursor,\r\n }}\r\n >\r\n </canvas>\r\n </div>\r\n </div>\r\n {currentPolygon?.closed && (\r\n <div class=\"w-full\">\r\n <polygon-buttons\r\n currentTool={this.currentTool.name}\r\n calculateSolarPanels={() =>\r\n this.calculateSolarPanels()}\r\n selectEdgeTool={() =>\r\n this.handleToolSelect(markRoofEdgeTool)}\r\n />\r\n </div>\r\n )}\r\n {!state.isMobile && (\r\n <div class=\"w-full\">\r\n <polygon-information\r\n currentPolygon={currentPolygon}\r\n positionedPanels={currentPolygon\r\n ? this\r\n .roofPolygonsSolarPanels[currentPolygon._id]\r\n ?.positionedPanels\r\n : undefined}\r\n handleAzimuthChange={(event) =>\r\n this.handleAzimuthChange(event)}\r\n handlePitchChange={(event) =>\r\n this.handlePitchChange(event)}\r\n calculateSolarPanels={() =>\r\n this.calculateSolarPanels()}\r\n />\r\n </div>\r\n )}\r\n <div class=\"w-full\">\r\n <solar-system-form\r\n systemConfigs={this.roofPolygonsSolarPanels}\r\n roofPolygons={this.roofPolygons}\r\n obstructionPolygons={this.obstructionPolygons}\r\n />\r\n </div>\r\n {this.showSettings && (\r\n <settings-modal\r\n settings={state.settings}\r\n onClose={this.handleSettingsClose}\r\n onSave={this.handleSettingsSave}\r\n />\r\n )}\r\n </div>\r\n );\r\n }\r\n}\r\n"],"version":3}
|
|
1
|
+
{"file":"p-r9wMCtI3.js","mappings":"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","names":["__stencil_proxyCustomElement","HTMLElement","uuidv4"],"sources":["src/utils/visualize.ts","src/utils/render/projection.ts","src/utils/render/polygon.ts","src/utils/render/color.ts","../../node_modules/uuid/dist/esm-browser/stringify.js","../../node_modules/uuid/dist/esm-browser/rng.js","../../node_modules/uuid/dist/esm-browser/native.js","../../node_modules/uuid/dist/esm-browser/v4.js","src/utils/geometry/fitting.ts","src/utils/geometry/gridMatch.ts","src/output.css?tag=map-draw","src/components/map-draw/map-draw.tsx"],"sourcesContent":["/*\r\n Copyright 2023 Google LLC\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n https://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n */\r\n\r\n import { PositionedSolarPanel } from './geometry/fitting';\r\nimport type { Bounds, GeoTiff, InternalSolarPanelConfig } from './solar';\r\n\r\n // [START visualize_render_rgb]\r\n /**\r\n * Renders an RGB GeoTiff image into an HTML canvas.\r\n *\r\n * The GeoTiff image must include 3 rasters (bands) which\r\n * correspond to [Red, Green, Blue] in that order.\r\n *\r\n * @param {GeoTiff} rgb GeoTiff with RGB values of the image.\r\n * @param {GeoTiff} mask Optional mask for transparency, defaults to opaque.\r\n * @return {HTMLCanvasElement} Canvas element with the rendered image.\r\n */\r\n export function renderRGB(rgb: GeoTiff, mask?: GeoTiff, canvas?: HTMLCanvasElement | null): HTMLCanvasElement {\r\n // Create an HTML canvas to draw the image.\r\n // https://www.w3schools.com/tags/canvas_createimagedata.asp\r\n if (!canvas) {\r\n canvas = document.createElement('canvas');\r\n }\r\n \r\n // Set the canvas size to the mask size if it's available,\r\n // otherwise set it to the RGB data layer size.\r\n canvas.width = mask ? mask.width : rgb.width;\r\n canvas.height = mask ? mask.height : rgb.height;\r\n \r\n // Since the mask size can be different than the RGB data layer size,\r\n // we calculate the \"delta\" between the RGB layer size and the canvas/mask\r\n // size. For example, if the RGB layer size is the same as the canvas size,\r\n // the delta is 1. If the RGB layer size is smaller than the canvas size,\r\n // the delta would be greater than 1.\r\n // This is used to translate the index from the canvas to the RGB layer.\r\n const dw = rgb.width / canvas.width;\r\n const dh = rgb.height / canvas.height;\r\n \r\n // Get the canvas image data buffer.\r\n const ctx = canvas.getContext('2d')!;\r\n const img = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n \r\n // Fill in every pixel in the canvas with the corresponding RGB layer value.\r\n // Since Javascript doesn't support multidimensional arrays or tensors,\r\n // everything is stored in flat arrays and we have to keep track of the\r\n // indices for each row and column ourselves.\r\n for (let y = 0; y < canvas.height; y++) {\r\n for (let x = 0; x < canvas.width; x++) {\r\n // RGB index keeps track of the RGB layer position.\r\n // This is multiplied by the deltas since it might be a different\r\n // size than the image size.\r\n const rgbIdx = Math.floor(y * dh) * rgb.width + Math.floor(x * dw);\r\n // Mask index keeps track of the mask layer position.\r\n const maskIdx = y * canvas.width + x;\r\n \r\n // Image index keeps track of the canvas image position.\r\n // HTML canvas expects a flat array with consecutive RGBA values.\r\n // Each value in the image buffer must be between 0 and 255.\r\n // The Alpha value is the transparency of that pixel,\r\n // if a mask was not provided, we default to 255 which is opaque.\r\n const imgIdx = y * canvas.width * 4 + x * 4;\r\n const factor = 0.8;\r\n img.data[imgIdx + 0] = Math.round(rgb.rasters[0][rgbIdx] * factor); // Red\r\n img.data[imgIdx + 1] = Math.round(rgb.rasters[1][rgbIdx] * factor); // Green\r\n img.data[imgIdx + 2] = Math.round(rgb.rasters[2][rgbIdx] * factor); // Blue\r\n img.data[imgIdx + 3] = mask // Alpha\r\n ? mask.rasters[0][maskIdx] * 255\r\n : 255;\r\n }\r\n }\r\n \r\n // Draw the image data buffer into the canvas context.\r\n ctx.putImageData(img, 0, 0);\r\n return canvas;\r\n }\r\n // [END visualize_render_rgb]\r\n \r\n // [START visualize_render_palette]\r\n /**\r\n * Renders a single value GeoTiff image into an HTML canvas.\r\n *\r\n * The GeoTiff image must include 1 raster (band) which contains\r\n * the values we want to display.\r\n *\r\n * @param {GeoTiff} data GeoTiff with the values of interest.\r\n * @param {GeoTiff} mask Optional mask for transparency, defaults to opaque.\r\n * @param {string[]} colors Hex color palette, defaults to ['000000', 'ffffff'].\r\n * @param {number} min Minimum value of the data range, defaults to 0.\r\n * @param {number} max Maximum value of the data range, defaults to 1.\r\n * @param {number} index Raster index for the data, defaults to 0.\r\n * @return {HTMLCanvasElement} Canvas element with the rendered image.\r\n */\r\n export function renderPalette({\r\n data,\r\n mask,\r\n colors,\r\n min,\r\n max,\r\n index,\r\n canvas,\r\n }: {\r\n data: GeoTiff;\r\n mask?: GeoTiff;\r\n colors?: string[];\r\n min?: number;\r\n max?: number;\r\n index?: number;\r\n canvas?: HTMLCanvasElement | null\t;\r\n }): HTMLCanvasElement {\r\n // First create a palette from a list of hex colors.\r\n const palette = createPalette(colors ?? ['000000', 'ffffff']);\r\n // Normalize each value of our raster/band of interest into indices,\r\n // such that they always map into a value within the palette.\r\n const indices = data.rasters[index ?? 0]\r\n .map((x) => normalize(x, max ?? 1, min ?? 0))\r\n .map((x) => Math.round(x * (palette.length - 1)));\r\n return renderRGB(\r\n {\r\n ...data,\r\n // Map each index into the corresponding RGB values.\r\n rasters: [\r\n indices.map((i: number) => palette[i].r),\r\n indices.map((i: number) => palette[i].g),\r\n indices.map((i: number) => palette[i].b),\r\n ],\r\n },\r\n mask,\r\n canvas,\r\n );\r\n }\r\n \r\n /**\r\n * Creates an {r, g, b} color palette from a hex list of colors.\r\n *\r\n * Each {r, g, b} value is a number between 0 and 255.\r\n * The created palette is always of size 256, regardless of the number of\r\n * hex colors passed in. Inbetween values are interpolated.\r\n *\r\n * @param {string[]} hexColors List of hex colors for the palette.\r\n * @return {{r, g, b}[]} RGB values for the color palette.\r\n */\r\n export function createPalette(hexColors: string[]): { r: number; g: number; b: number }[] {\r\n // Map each hex color into an RGB value.\r\n const rgb = hexColors.map(colorToRGB);\r\n // Create a palette with 256 colors derived from our rgb colors.\r\n const size = 256;\r\n const step = (rgb.length - 1) / (size - 1);\r\n return Array(size)\r\n .fill(0)\r\n .map((_, i) => {\r\n // Get the lower and upper indices for each color.\r\n const index = i * step;\r\n const lower = Math.floor(index);\r\n const upper = Math.ceil(index);\r\n // Interpolate between the colors to get the shades.\r\n return {\r\n r: lerp(rgb[lower].r, rgb[upper].r, index - lower),\r\n g: lerp(rgb[lower].g, rgb[upper].g, index - lower),\r\n b: lerp(rgb[lower].b, rgb[upper].b, index - lower),\r\n };\r\n });\r\n }\r\n \r\n /**\r\n * Convert a hex color into an {r, g, b} color.\r\n *\r\n * @param {string} color Hex color like 0099FF or #0099FF.\r\n * @return {{r, g, b}} RGB values for that color.\r\n */\r\n export function colorToRGB(color: string): { r: number; g: number; b: number } {\r\n const hex = color.startsWith('#') ? color.slice(1) : color;\r\n return {\r\n r: parseInt(hex.substring(0, 2), 16),\r\n g: parseInt(hex.substring(2, 4), 16),\r\n b: parseInt(hex.substring(4, 6), 16),\r\n };\r\n }\r\n \r\n /**\r\n * Normalizes a number to a given data range.\r\n *\r\n * @param {number} x Value of interest.\r\n * @param {number} max Maximum value in data range, defaults to 1.\r\n * @param {number} min Minimum value in data range, defaults to 0.\r\n * @return {number} Normalized value.\r\n */\r\n export function normalize(x: number, max: number = 1, min: number = 0): number {\r\n const y = (x - min) / (max - min);\r\n return clamp(y, 0, 1);\r\n }\r\n \r\n /**\r\n * Calculates the linear interpolation for a value within a range.\r\n *\r\n * @param {number} x Lower value in the range, when `t` is 0.\r\n * @param {number} y Upper value in the range, when `t` is 1.\r\n * @param {number} t \"Time\" between 0 and 1.\r\n * @return {number} Inbetween value for that \"time\".\r\n */\r\n export function lerp(x: number, y: number, t: number): number {\r\n return x + t * (y - x);\r\n }\r\n \r\n /**\r\n * Clamps a value to always be within a range.\r\n *\r\n * @param {number} x Value to clamp.\r\n * @param {number} min Minimum value in the range.\r\n * @param {number} max Maximum value in the range.\r\n * @return {number} Clamped value.\r\n */\r\n export function clamp(x: number, min: number, max: number): number {\r\n return Math.min(Math.max(x, min), max);\r\n }\r\n // [END visualize_render_palette]\r\n \r\n export function rgbToColor({ r, g, b }: { r: number; g: number; b: number }): string {\r\n const f = (x: number) => {\r\n const hex = Math.round(x).toString(16);\r\n return hex.length == 1 ? `0${hex}` : hex;\r\n };\r\n return `#${f(r)}${f(g)}${f(b)}`;\r\n }\r\n\r\n export function renderAzimuth(azimuth: number, ctx: CanvasRenderingContext2D) {\r\n if (azimuth === undefined) {\r\n return;\r\n }\r\n ctx.save();\r\n ctx.moveTo(0, 0);\r\n ctx.rotate((azimuth - 90) * Math.PI / 180);\r\n ctx.translate(ctx.canvas.width-100, 100);\r\n \r\n // Set arrow style\r\n ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';\r\n ctx.lineWidth = 2;\r\n\r\n ctx.moveTo(-50, 0);\r\n ctx.lineTo(50,0);\r\n ctx.lineTo(40,-10);\r\n ctx.moveTo(50,0);\r\n ctx.lineTo(40,10);\r\n ctx.stroke();\r\n\r\n ctx.moveTo(0, 0);\r\n ctx.beginPath();\r\n ctx.arc(0, 0, 50, 0, Math.PI * 2);\r\n ctx.stroke();\r\n\r\n // Arrow parameters\r\n // const arrowLength = 100;\r\n // const arrowHeadLength = 15;\r\n // const arrowHeadAngle = Math.PI / 6; // 30 degrees\r\n\r\n // // Convert azimuth to radians (subtract 90 degrees to align with standard compass)\r\n // const angle = (azimuth - 90) * Math.PI / 180;\r\n\r\n // // Calculate arrow end point\r\n // const endX = arrowLength * Math.cos(angle);\r\n // const endY = arrowLength * Math.sin(angle);\r\n\r\n // // Draw main arrow line\r\n // ctx.beginPath();\r\n // ctx.moveTo(0, 0);\r\n // ctx.lineTo(endX, endY);\r\n // ctx.stroke();\r\n\r\n // // Calculate arrowhead points\r\n // const arrowHeadAngle1 = angle + Math.PI - arrowHeadAngle;\r\n // const arrowHeadAngle2 = angle + Math.PI + arrowHeadAngle;\r\n\r\n // const arrowHead1X = endX + arrowHeadLength * Math.cos(arrowHeadAngle1);\r\n // const arrowHead1Y = endY + arrowHeadLength * Math.sin(arrowHeadAngle1);\r\n // const arrowHead2X = endX + arrowHeadLength * Math.cos(arrowHeadAngle2);\r\n // const arrowHead2Y = endY + arrowHeadLength * Math.sin(arrowHeadAngle2);\r\n\r\n // // Draw arrowhead\r\n // ctx.beginPath();\r\n // ctx.moveTo(endX, endY);\r\n // ctx.lineTo(arrowHead1X, arrowHead1Y);\r\n // ctx.lineTo(arrowHead2X, arrowHead2Y);\r\n // ctx.closePath();\r\n // ctx.fill();\r\n\r\n // ctx.translate(ctx.canvas.width/2, 50);\r\n\r\n ctx.restore();\r\n\r\n console.log(\"renderAzimuth\", azimuth);\r\n }\r\n\r\n export function renderSolarPanel(solarPanel: PositionedSolarPanel, ctx: CanvasRenderingContext2D, panelWidth: number, panelHeight: number, azimuthAngle: number, pitchAngle: number) {\r\n const { x, y } = solarPanel.pixelPosition;\r\n let width = panelWidth;\r\n let height = panelHeight * Math.cos(pitchAngle * Math.PI / 180);\r\n if (solarPanel.horizontal) {\r\n width = panelHeight;\r\n height = panelWidth * Math.cos(pitchAngle * Math.PI / 180);\r\n }\r\n\r\n // Save the current context state\r\n ctx.save();\r\n \r\n // Translate to the panel's center point\r\n ctx.translate(x, y);\r\n \r\n // Rotate by the azimuth angle (convert to radians)\r\n ctx.rotate((azimuthAngle * Math.PI) / 180);\r\n \r\n // Draw panel rectangle centered at origin (since we translated)\r\n ctx.fillStyle = 'rgba(0, 51, 204, 0.8)';\r\n ctx.fillRect(-width/2, -height/2, width, height);\r\n \r\n // Draw panel border\r\n ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';\r\n ctx.lineWidth = 1;\r\n ctx.strokeRect(-width/2, -height/2, width, height);\r\n \r\n // Restore the context state\r\n ctx.restore();\r\n}\r\n\r\n export function renderPanels({canvas, panelConfig, bounds, zoom, roofSegments}: \r\n {canvas: HTMLCanvasElement | null, panelConfig: InternalSolarPanelConfig, bounds: Bounds, zoom: number, roofSegments: Record<number, { pitchDegrees: number; azimuthDegrees: number }>}): HTMLCanvasElement {\r\n if (!canvas) {\r\n canvas = document.createElement('canvas');\r\n }\r\n \r\n const ctx = canvas.getContext(\"2d\")!;\r\n\r\n // Calculate pre zoomed dimensions the canvas is already zoomed\r\n const preZoomedWidth = Math.floor(canvas.width / zoom);\r\n const preZoomedHeight = Math.floor(canvas.height / zoom);\r\n const startX = Math.floor((preZoomedWidth - canvas.width) / 2);\r\n const startY = Math.floor((preZoomedHeight - canvas.height) / 2);\r\n\r\n // Calculate the scale factors to convert lat/lng to pixel coordinates\r\n const latToPixel = (lat: number) => {\r\n return preZoomedHeight * (1 - (lat - bounds.south) / (bounds.north - bounds.south)) - startY;\r\n };\r\n \r\n const lngToPixel = (lng: number) => {\r\n return preZoomedWidth * (lng - bounds.west) / (bounds.east - bounds.west) - startX;\r\n };\r\n \r\n // Draw each panel\r\n for (const panel of panelConfig.panels) {\r\n // Convert panel center coordinates to pixel coordinates\r\n const centerX = lngToPixel(panel.center.longitude);\r\n const centerY = latToPixel(panel.center.latitude);\r\n \r\n // Calculate panel dimensions (assuming standard panel size)\r\n const panelWidth = panel.orientation === 'LANDSCAPE' ? 19 : 10; // pixels\r\n const panelHeight = panel.orientation === 'LANDSCAPE' ? 10 : 19;\r\n \r\n // Get the roof segment's azimuth angle for this panel\r\n const roofSegment = roofSegments[panel.segmentIndex];\r\n const azimuthAngle = roofSegment ? roofSegment.azimuthDegrees : 0;\r\n \r\n // Save the current context state\r\n ctx.save();\r\n \r\n // Translate to the panel's center point\r\n ctx.translate(centerX, centerY);\r\n \r\n // Rotate by the azimuth angle (convert to radians)\r\n ctx.rotate((azimuthAngle * Math.PI) / 180);\r\n \r\n // Draw panel rectangle centered at origin (since we translated)\r\n ctx.fillStyle = 'rgba(115, 143, 255, 1)';\r\n ctx.fillRect(-panelWidth/2, -panelHeight/2, panelWidth, panelHeight);\r\n \r\n // Draw panel border\r\n ctx.strokeStyle = 'rgba(0, 0, 0, 0.8)';\r\n ctx.lineWidth = 1;\r\n ctx.strokeRect(-panelWidth/2, -panelHeight/2, panelWidth, panelHeight);\r\n \r\n // Restore the context state\r\n ctx.restore();\r\n }\r\n \r\n return canvas;\r\n }\r\n \r\n export function renderCombinedWithZoom({\r\n rgb,\r\n zoom = 1,\r\n canvas,\r\n}: {\r\n rgb: GeoTiff;\r\n zoom?: number;\r\n canvas?: HTMLCanvasElement | null;\r\n}): HTMLCanvasElement {\r\n // First render the RGB image\r\n const rgbCanvas = renderRGB(rgb, undefined, canvas);\r\n const ctx = rgbCanvas.getContext(\"2d\")!;\r\n const imgData = ctx.getImageData(0, 0, rgbCanvas.width, rgbCanvas.height);\r\n\r\n // Calculate the center portion to show based on zoom\r\n const width = rgbCanvas.width;\r\n const height = rgbCanvas.height;\r\n const zoomedWidth = Math.floor(width * zoom);\r\n const zoomedHeight = Math.floor(height * zoom);\r\n const startX = Math.floor((width - zoomedWidth) / 2);\r\n const startY = Math.floor((height - zoomedHeight) / 2);\r\n\r\n // Create a new image data for the zoomed portion\r\n const zoomedImgData = new ImageData(zoomedWidth, zoomedHeight);\r\n \r\n // Copy RGB data and apply palette where mask is non-zero\r\n for (let y = 0; y < height; y++) {\r\n for (let x = 0; x < width; x++) {\r\n const i = (y * width + x) * 4;\r\n \r\n if (x >= startX && x < startX + zoomedWidth && \r\n y >= startY && y < startY + zoomedHeight) {\r\n // Calculate position in zoomed image\r\n const zoomedX = x - startX;\r\n const zoomedY = y - startY;\r\n const zoomedI = (zoomedY * zoomedWidth + zoomedX) * 4;\r\n \r\n zoomedImgData.data[zoomedI] = imgData.data[i];\r\n zoomedImgData.data[zoomedI + 1] = imgData.data[i + 1];\r\n zoomedImgData.data[zoomedI + 2] = imgData.data[i + 2];\r\n zoomedImgData.data[zoomedI + 3] = 255; // Alpha channel\r\n }\r\n }\r\n }\r\n\r\n // Resize canvas to match zoomed dimensions\r\n rgbCanvas.width = zoomedWidth;\r\n rgbCanvas.height = zoomedHeight;\r\n \r\n // Put the zoomed image data back to the canvas\r\n ctx.putImageData(zoomedImgData, 0, 0);\r\n return rgbCanvas;\r\n}\r\n ","import { Point } from \"../../types/shapes\";\r\n\r\nexport function projectPointPerpendicularToLine({\r\n x,\r\n y,\r\n lastPoint,\r\n secondLastPoint,\r\n}: {\r\n x: number;\r\n y: number;\r\n lastPoint: { x: number; y: number };\r\n secondLastPoint: { x: number; y: number };\r\n}): Point {\r\n\r\n // Calculate the direction vector of the last line\r\n const dx = lastPoint.x - secondLastPoint.x;\r\n const dy = lastPoint.y - secondLastPoint.y;\r\n\r\n // Calculate perpendicular vector (rotate 90 degrees)\r\n const perpDx = -dy;\r\n const perpDy = dx;\r\n\r\n // Normalize the perpendicular vector\r\n const perpLength = Math.sqrt(perpDx * perpDx + perpDy * perpDy);\r\n const normalizedPerpDx = perpDx / perpLength;\r\n const normalizedPerpDy = perpDy / perpLength;\r\n\r\n // Project the mouse point onto the perpendicular line\r\n const vectorToMouse = {\r\n x: x - lastPoint.x,\r\n y: y - lastPoint.y,\r\n };\r\n\r\n // Calculate the projection length (dot product)\r\n const projectionLength = vectorToMouse.x * normalizedPerpDx +\r\n vectorToMouse.y * normalizedPerpDy;\r\n\r\n // Calculate the new point position using the projected length\r\n x = lastPoint.x + normalizedPerpDx * projectionLength;\r\n y = lastPoint.y + normalizedPerpDy * projectionLength;\r\n return { x, y };\r\n}\r\n","import { DOTTED_LINE_COLOR } from \"../../constants\";\r\nimport { Point, Polygon } from \"../../types/shapes\";\r\nimport { projectPointPerpendicularToLine } from \"./projection\";\r\n\r\nexport interface DrawPolygonProps {\r\n polygonCtx: CanvasRenderingContext2D;\r\n polygonCanvas: HTMLCanvasElement;\r\n polygon: Polygon;\r\n pixelInMeters: number;\r\n shiftKeyPressed: boolean;\r\n mousePoint: Point | null;\r\n strokeColor: string;\r\n highlightColor: string;\r\n fillColor?: string;\r\n highlightedEdge?: { pointA: Point; pointB: Point } | null;\r\n}\r\n\r\nexport interface Line{\r\n start: Point;\r\n end: Point;\r\n}\r\n\r\nexport interface DrawCircleProps {\r\n ctx: CanvasRenderingContext2D;\r\n x: number;\r\n y: number;\r\n radius: number;\r\n strokeStyle?: string;\r\n lineWidth?: number;\r\n}\r\n\r\nexport function drawPolygon({\r\n polygonCtx, polygonCanvas, polygon, shiftKeyPressed, mousePoint, strokeColor, fillColor, highlightedEdge, highlightColor\r\n}: DrawPolygonProps) {\r\n if (!polygonCtx || !polygonCanvas) return;\r\n\r\n // Draw the polygon\r\n polygonCtx.beginPath();\r\n polygonCtx.strokeStyle = strokeColor;\r\n polygonCtx.lineWidth = 2;\r\n\r\n polygon.points.forEach((point, index) => {\r\n if (index === 0) {\r\n polygonCtx.moveTo(point.x, point.y);\r\n } else {\r\n polygonCtx.lineTo(point.x, point.y);\r\n }\r\n });\r\n\r\n if (polygon.closed) {\r\n polygonCtx.lineTo(polygon.points[0].x, polygon.points[0].y);\r\n if (fillColor) {\r\n polygonCtx.fillStyle = fillColor;\r\n polygonCtx.fill();\r\n }\r\n }\r\n\r\n if (polygon.points.length > 0) {\r\n polygonCtx.stroke();\r\n }\r\n\r\n if (highlightedEdge && polygon.closed) {\r\n polygonCtx.beginPath();\r\n polygonCtx.strokeStyle = highlightColor;\r\n polygonCtx.lineWidth = 2;\r\n polygonCtx.moveTo(highlightedEdge.pointA.x, highlightedEdge.pointA.y);\r\n polygonCtx.lineTo(highlightedEdge.pointB.x, highlightedEdge.pointB.y);\r\n polygonCtx.stroke();\r\n polygonCtx.strokeStyle = strokeColor;\r\n polygonCtx.lineWidth = 1;\r\n }\r\n\r\n if (polygon.points.length > 1 && !polygon.closed && shiftKeyPressed) {\r\n const projectedPoint = projectPointPerpendicularToLine({\r\n x: mousePoint.x,\r\n y: mousePoint.y,\r\n lastPoint: polygon.points[polygon.points.length - 1],\r\n secondLastPoint: polygon.points[polygon.points.length - 2],\r\n });\r\n drawPerpendicularDottedLine({\r\n ctx: polygonCtx,\r\n startPoint: projectedPoint,\r\n endPoint: polygon.points[polygon.points.length - 1],\r\n strokeStyle: DOTTED_LINE_COLOR,\r\n });\r\n }\r\n\r\n if (shiftKeyPressed && polygon.points.length > 1 && !polygon.closed) {\r\n const projectedPoint = projectPointPerpendicularToLine({\r\n x: mousePoint.x,\r\n y: mousePoint.y,\r\n lastPoint: polygon.points[polygon.points.length - 1],\r\n secondLastPoint: polygon.points[polygon.points.length - 2],\r\n });\r\n drawCircle({\r\n ctx: polygonCtx,\r\n x: projectedPoint.x,\r\n y: projectedPoint.y,\r\n radius: 5,\r\n strokeStyle: DOTTED_LINE_COLOR,\r\n });\r\n }\r\n\r\n // Draw circles around each point\r\n polygon.points.forEach((point) => {\r\n polygonCtx.beginPath();\r\n const strokeStyle = strokeColor;\r\n const distance = Math.sqrt(\r\n Math.pow(point.x - mousePoint.x, 2) + Math.pow(point.y - mousePoint.y, 2)\r\n );\r\n\r\n // Highlight the point if it's being hovered or dragged\r\n if (\r\n distance < 10\r\n ) {\r\n drawCircle({\r\n ctx: polygonCtx,\r\n x: point.x,\r\n y: point.y,\r\n strokeStyle,\r\n radius: 8,\r\n });\r\n } else {\r\n drawCircle({\r\n ctx: polygonCtx,\r\n x: point.x,\r\n y: point.y,\r\n strokeStyle,\r\n radius: 5,\r\n });\r\n }\r\n\r\n polygonCtx.stroke();\r\n });\r\n}\r\n\r\nexport function drawCircle({\r\n ctx,\r\n x,\r\n y,\r\n radius,\r\n strokeStyle = \"black\",\r\n lineWidth = 2\r\n}: DrawCircleProps) {\r\n ctx.beginPath();\r\n ctx.strokeStyle = strokeStyle;\r\n ctx.lineWidth = lineWidth;\r\n \r\n ctx.arc(x, y, radius, 0, 2 * Math.PI);\r\n ctx.stroke();\r\n}\r\n\r\nexport function drawPerpendicularDottedLine({\r\n ctx,\r\n startPoint,\r\n endPoint,\r\n dashPattern = [5, 5],\r\n strokeStyle = \"black\",\r\n lineWidth = 2\r\n}: {\r\n ctx: CanvasRenderingContext2D;\r\n startPoint: Point;\r\n endPoint: Point;\r\n dashPattern?: number[];\r\n strokeStyle?: string;\r\n lineWidth?: number;\r\n}) {\r\n // Set up the line style\r\n ctx.beginPath();\r\n ctx.strokeStyle = strokeStyle;\r\n ctx.lineWidth = lineWidth;\r\n ctx.setLineDash(dashPattern);\r\n \r\n // Draw the dotted line\r\n ctx.moveTo(startPoint.x, startPoint.y);\r\n ctx.lineTo(endPoint.x, endPoint.y);\r\n ctx.stroke();\r\n \r\n // Reset the line dash\r\n ctx.setLineDash([]);\r\n}\r\n\r\nexport function isPointOnBorder(point: Point, polygon: Polygon): boolean {\r\n if (!polygon.closed || polygon.points.length < 3) return false;\r\n\r\n const x = point.x;\r\n const y = point.y;\r\n\r\n // For each edge of the polygon\r\n for (let i = 0; i < polygon.points.length; i++) {\r\n const p1 = polygon.points[i];\r\n const p2 = polygon.points[(i + 1) % polygon.points.length];\r\n // calculate the distance from point p1 to p2\r\n const distance = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\r\n const distanceToPoint = Math.sqrt(Math.pow(p1.x - x, 2) + Math.pow(p1.y - y, 2));\r\n const distanceFromPoint = Math.sqrt(Math.pow(p2.x - x, 2) + Math.pow(p2.y - y, 2));\r\n if (distance === distanceToPoint + distanceFromPoint) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function isPointInPolygon(point: Point, polygon: Polygon): boolean {\r\n if (!polygon.closed || polygon.points.length < 3) return false;\r\n\r\n const num_vertices = polygon.points.length;\r\n const x = point.x;\r\n const y = point.y;\r\n let inside = false;\r\n\r\n let p1 = polygon.points[0];\r\n let p2: Point;\r\n\r\n for (let i = 1; i <= num_vertices; i++) {\r\n p2 = polygon.points[i % num_vertices];\r\n\r\n if (y > Math.min(p1.y, p2.y)) {\r\n if (y <= Math.max(p1.y, p2.y)) {\r\n if (x <= Math.max(p1.x, p2.x)) {\r\n const x_intersection = ((y - p1.y) * (p2.x - p1.x)) / (p2.y - p1.y) + p1.x;\r\n\r\n if (p1.x === p2.x || x <= x_intersection) {\r\n inside = !inside;\r\n }\r\n }\r\n }\r\n }\r\n\r\n p1 = p2;\r\n }\r\n\r\n return inside;\r\n}","import { Polygon, SelectedPolygon } from \"../../types/shapes\";\r\nimport { SolarExpertConfig } from \"../../config\";\r\n\r\n\r\nexport function getFillColor(selectedPolygon: SelectedPolygon | null, hoveredPolygon: SelectedPolygon | null, _id: string, polygon: Polygon, config: SolarExpertConfig): string | undefined {\r\n const isHovered = hoveredPolygon?.type === polygon.type && hoveredPolygon?._id === _id;\r\n if (isHovered) {\r\n return polygon.type === \"roof\" ? config.roofPolygonHoverFillColor : config.obstructionPolygonHoverFillColor;\r\n }\r\n \r\n const isSelected = selectedPolygon?.type === polygon.type && selectedPolygon?._id === _id;\r\n\r\n if (isSelected) {\r\n return polygon.type === \"roof\" ? config.roofPolygonSelectedFillColor : config.obstructionPolygonSelectedFillColor;\r\n }\r\n\r\n if (polygon.type === \"roof\") {\r\n return polygon.closed ? config.roofPolygonFillColor : undefined;\r\n }\r\n return polygon.closed ? config.obstructionPolygonFillColor : undefined;\r\n}\r\n","import validate from './validate.js';\n\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nvar byteToHex = [];\nfor (var i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n //\n // Note to future-self: No, you can't remove the `toLowerCase()` call.\n // REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351\n return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n var uuid = unsafeStringify(arr, offset);\n // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;","// Unique ID creation requires a high quality random # generator. In the browser we therefore\n// require the crypto API and do not support built-in fallback to lower quality random number\n// generators (like Math.random()).\n\nvar getRandomValues;\nvar rnds8 = new Uint8Array(16);\nexport default function rng() {\n // lazy load so that environments that need to polyfill have a chance to do so\n if (!getRandomValues) {\n // getRandomValues needs to be invoked in a context where \"this\" is a Crypto implementation.\n getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);\n if (!getRandomValues) {\n throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n }\n }\n return getRandomValues(rnds8);\n}","var randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nexport default {\n randomUUID\n};","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n var rnds = options.random || (options.rng || rng)();\n\n // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80;\n\n // Copy bytes to buffer, if provided\n if (buf) {\n offset = offset || 0;\n for (var i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;","import { LineSegment, Polygon, SegmentMatch } from \"../../types/shapes\";\r\nimport { Bounds, LatLng, RoofSegmentSizeAndSunshineStats, SolarPanelType } from \"../solar\";\r\nimport { latLngToPixel } from \"../utils\";\r\nimport { Point } from \"../../types/shapes\";\r\nimport { isPointInPolygon, isPointOnBorder, Line } from \"../render/polygon\";\r\n\r\n\r\nexport interface SolarPanelSystemPart {\r\n positionedPanels: PositionedSolarPanel[];\r\n sunniness: number;\r\n}\r\n\r\nexport interface PositionedSolarPanel {\r\n panel: SolarPanelType;\r\n pixelPosition: {\r\n x: number;\r\n y: number;\r\n };\r\n horizontal: boolean;\r\n}\r\n\r\n/**\r\n * Get the intersections of a line parallel to the x-axis of the projected coordinate system with a polygon.\r\n * @param projectedPoint the point to draw the line from\r\n * @param projectedPolygon the polygon to get the intersections with\r\n * @returns the intersections of the line with the polygon\r\n */\r\nexport function getIntersections(projectedPoint: Point, projectedPolygon: Polygon): Point[] {\r\n const intersections: Point[] = [];\r\n\r\n if (projectedPolygon.points.length === 0) {\r\n return intersections;\r\n }\r\n \r\n // For each edge of the polygon\r\n for (let i = 0; i < projectedPolygon.points.length; i++) {\r\n const p1 = projectedPolygon.points[i];\r\n const p2 = projectedPolygon.points[(i + 1) % projectedPolygon.points.length];\r\n \r\n // Calculate intersection point\r\n const t = (projectedPoint.y - p1.y) / (p2.y - p1.y);\r\n const x = p1.x + t * (p2.x - p1.x);\r\n \r\n if (t > 0 && t <= 1) {\r\n intersections.push({ x, y: projectedPoint.y });\r\n }\r\n if (t === 0) {\r\n intersections.push({ x: p1.x, y: projectedPoint.y });\r\n }\r\n }\r\n \r\n // Sort intersections by y-coordinate\r\n return intersections.sort((a, b) => a.x - b.x);\r\n}\r\n\r\nexport function projectPoint(point: Point, azimuth: number): Point {\r\n const angle = azimuth * (Math.PI / 180);\r\n const x = point.x * Math.cos(angle) - point.y * Math.sin(angle);\r\n const y = point.x * Math.sin(angle) + point.y * Math.cos(angle);\r\n return { x, y };\r\n}\r\n\r\nexport function projectPolygon(polygon: Polygon, azimuth: number): Polygon {\r\n return {\r\n points: polygon.points.map((point) => projectPoint(point, azimuth)),\r\n type: polygon.type,\r\n closed: polygon.closed,\r\n _id: polygon._id,\r\n details: polygon.details,\r\n };\r\n}\r\n\r\nexport function offsetPolygon(polygon: Polygon, offset?: {x: number, y: number}): {polygon: Polygon, offset: {x: number, y: number}} {\r\n if (polygon.points.length === 0) {\r\n return { polygon: polygon, offset: {x: 0, y: 0} };\r\n }\r\n\r\n let offsetX = 0;\r\n let offsetY = 0;\r\n if (!offset) {\r\n const minX = Math.min(...polygon.points.map((point) => point.x));\r\n const minY = Math.min(...polygon.points.map((point) => point.y));\r\n const maxX = Math.max(...polygon.points.map((point) => point.x));\r\n const maxY = Math.max(...polygon.points.map((point) => point.y));\r\n\r\n offsetX = minX + (maxX - minX) / 2;\r\n offsetY = minY + (maxY - minY) / 2;\r\n }\r\n else {\r\n offsetX = offset.x;\r\n offsetY = offset.y;\r\n }\r\n\r\n const newPoints = polygon.points.map((point) => ({\r\n x: point.x - offsetX,\r\n y: point.y - offsetY,\r\n }));\r\n\r\n return { polygon: { ...polygon, points: newPoints }, offset: {x: offsetX, y: offsetY} };\r\n}\r\n\r\nfunction equalsPoints(point1: Point, point2: Point): boolean {\r\n return point1.x === point2.x && point1.y === point2.y;\r\n}\r\n\r\n/**\r\n * Checks if two lines intersect.\r\n * if the lines intersect in a start or end point they are not considered as intersecting\r\n * @param line1 The first line.\r\n * @param line2 The second line.\r\n * @returns True if the lines intersect, false otherwise.\r\n */\r\nexport function intersects(line1: Line, line2: Line): boolean {\r\n // Get the points of each line\r\n const p1 = line1.start;\r\n const p2 = line1.end;\r\n const p3 = line2.start;\r\n const p4 = line2.end;\r\n\r\n if (equalsPoints(p1, p3) || equalsPoints(p1, p4) || equalsPoints(p2, p3) || equalsPoints(p2, p4)) {\r\n return false;\r\n }\r\n\r\n // Calculate the cross products\r\n const d1 = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);\r\n const d2 = (p4.x - p3.x) * (p2.y - p3.y) - (p4.y - p3.y) * (p2.x - p3.x);\r\n const d3 = (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);\r\n const d4 = (p2.x - p1.x) * (p4.y - p1.y) - (p2.y - p1.y) * (p4.x - p1.x);\r\n\r\n // Check if the lines intersect\r\n return (d1 * d2 < 0) && (d3 * d4 < 0);\r\n}\r\n\r\nexport function undoOffsetPolygon(polygon: Polygon, offset: {x: number, y: number}): Polygon {\r\n return {\r\n ...polygon,\r\n points: polygon.points.map((point) => ({\r\n x: point.x + offset.x,\r\n y: point.y + offset.y,\r\n })),\r\n };\r\n}\r\n\r\nexport function segmentPolygon(polygon: Polygon) {\r\n const segments: LineSegment[] = [];\r\n const segmentsMap: Record<string, boolean> = {};\r\n\r\n for (const point of polygon.points) {\r\n const intersections = getIntersections(point, polygon);\r\n for (const [index, intersection] of intersections.slice(0, -1).entries()) {\r\n const nextIntersection = intersections[index + 1];\r\n \r\n const halfPoint = {\r\n x: (intersection.x + nextIntersection.x) / 2,\r\n y: (intersection.y + nextIntersection.y) / 2,\r\n };\r\n\r\n const isInner = isPointInPolygon(halfPoint, polygon);\r\n const isOnBorder = isPointOnBorder(halfPoint, polygon);\r\n const key = `${intersection.x}-${intersection.y}-${nextIntersection.x}-${nextIntersection.y}`;\r\n \r\n if (segmentsMap[key]) {\r\n continue;\r\n }\r\n segments.push({ start: intersection, end: nextIntersection, type: isOnBorder ? \"border\" : (isInner ? \"inner\" : \"outer\") });\r\n segmentsMap[key] = true;\r\n }\r\n }\r\n return segments;\r\n}\r\n\r\n/**\r\n * for each segment this method will find all the following segments that are connected to it\r\n * \r\n * first the method subdivides the segments into y levels (all segments that have the same y coordinate are in the same level)\r\n * then it will check for each segment in each level if there is a following segment that is connected to it by checking it the \r\n * start point of the top segment to the end point of the bottom segment does not intersect with any of the polygon borders and the center point of the connection is in the polygon\r\n * \r\n * @param segments \r\n * @param roof \r\n * @returns \r\n */\r\nexport function matchSegments(segments: LineSegment[], roof: Polygon): {matches: SegmentMatch[], map: Record<string, LineSegment>} {\r\n const matches: SegmentMatch[] = [];\r\n const map: Record<string, LineSegment> = {};\r\n\r\n for (const segment of segments) {\r\n map[`${segment.start.x}-${segment.start.y}-${segment.end.x}-${segment.end.y}`] = segment;\r\n }\r\n \r\n // Group segments by y-coordinate (level)\r\n const levels: Record<number, LineSegment[]> = {};\r\n segments.forEach(segment => {\r\n const y = segment.start.y;\r\n if (!levels[y]) {\r\n levels[y] = [];\r\n }\r\n levels[y].push(segment);\r\n });\r\n\r\n // Sort levels by y-coordinate\r\n const sortedLevels = Object.keys(levels).map(Number).sort((a, b) => a - b);\r\n\r\n // For each level except the last one\r\n for (let i = 0; i < sortedLevels.length - 1; i++) {\r\n const currentLevel = levels[sortedLevels[i]];\r\n const nextLevel = levels[sortedLevels[i + 1]];\r\n\r\n // For each segment in current level\r\n for (const currentSegment of currentLevel) {\r\n if (currentSegment.type === \"outer\") {\r\n continue;\r\n }\r\n const matchedSegments: LineSegment[] = [];\r\n \r\n // For each segment in next level\r\n for (const nextSegment of nextLevel) {\r\n // Check if segments can be connected\r\n const connectionStart = currentSegment.start;\r\n const connectionEnd = nextSegment.end;\r\n\r\n let intersected = false;\r\n for (let i = 0; i < roof.points.length; i++) {\r\n const line = {\r\n start: roof.points[i],\r\n end: roof.points[(i + 1) % roof.points.length]\r\n };\r\n if (intersects(line, {start: connectionStart, end: connectionEnd})) {\r\n intersected = true;\r\n break;\r\n }\r\n }\r\n\r\n if (intersected) {\r\n continue;\r\n }\r\n\r\n // Check if center point of connection is inside polygon\r\n const centerPoint = {\r\n x: (connectionStart.x + connectionEnd.x) / 2,\r\n y: (connectionStart.y + connectionEnd.y) / 2\r\n };\r\n\r\n if (isPointInPolygon(centerPoint, roof)) {\r\n matchedSegments.push(nextSegment);\r\n }\r\n }\r\n\r\n if (matchedSegments.length > 0) {\r\n matches.push({\r\n segment: `${currentSegment.start.x}-${currentSegment.start.y}-${currentSegment.end.x}-${currentSegment.end.y}`,\r\n matchedSegments: matchedSegments.map(segment => `${segment.start.x}-${segment.start.y}-${segment.end.x}-${segment.end.y}`)\r\n });\r\n }\r\n }\r\n }\r\n\r\n return {matches, map};\r\n}\r\n\r\n\r\n/**\r\n * Uses the bounding box of the roof and the roof segment bounding boxes to find the best fitting roof segment.\r\n * @param roof the roof shape\r\n * @param roofSegmentStats the stats of the roof segments\r\n * @returns the best fitting roof segment\r\n */\r\nexport function getBestFittingRoofSegment(roof: Polygon, roofSegmentStats: RoofSegmentSizeAndSunshineStats[], bounds: Bounds, canvas: HTMLCanvasElement): RoofSegmentSizeAndSunshineStats {\r\n const polygonBounds = {\r\n minX: Math.min(...roof.points.map((p) => p.x)),\r\n maxX: Math.max(...roof.points.map((p) => p.x)),\r\n minY: Math.min(...roof.points.map((p) => p.y)),\r\n maxY: Math.max(...roof.points.map((p) => p.y)),\r\n };\r\n\r\n let bestSegment = null;\r\n let bestIoU = 0;\r\n\r\n for (const segment of roofSegmentStats) {\r\n const sw = latLngToPixel(bounds, canvas, {\r\n latitude: segment.boundingBox.sw.latitude,\r\n longitude: segment.boundingBox.sw.longitude,\r\n } as LatLng);\r\n const ne = latLngToPixel(bounds, canvas, {\r\n latitude: segment.boundingBox.ne.latitude,\r\n longitude: segment.boundingBox.ne.longitude,\r\n } as LatLng);\r\n const segmentBounds = {\r\n minX: sw.x,\r\n maxX: ne.x,\r\n minY: ne.y,\r\n maxY: sw.y,\r\n };\r\n\r\n // Calculate intersection\r\n const interLeft = Math.max(polygonBounds.minX, segmentBounds.minX);\r\n const interRight = Math.min(polygonBounds.maxX, segmentBounds.maxX);\r\n const interTop = Math.max(polygonBounds.minY, segmentBounds.minY);\r\n const interBottom = Math.min(polygonBounds.maxY, segmentBounds.maxY);\r\n\r\n const interWidth = interRight - interLeft;\r\n const interHeight = interBottom - interTop;\r\n let intersectionArea = 0;\r\n if (interWidth > 0 && interHeight > 0) {\r\n intersectionArea = interWidth * interHeight;\r\n }\r\n\r\n const polygonArea = (polygonBounds.maxX - polygonBounds.minX) * (polygonBounds.maxY - polygonBounds.minY);\r\n const segmentArea = (segmentBounds.maxX - segmentBounds.minX) * (segmentBounds.maxY - segmentBounds.minY);\r\n const unionArea = polygonArea + segmentArea - intersectionArea;\r\n const iou = unionArea > 0 ? intersectionArea / unionArea : 0;\r\n\r\n if (iou > bestIoU) {\r\n bestIoU = iou;\r\n bestSegment = segment;\r\n }\r\n }\r\n\r\n return bestSegment;\r\n}\r\n","import { COLUMN_SPACING, ROW_SPACING } from \"../../constants\";\r\nimport { Point, Polygon } from \"../../types/shapes\";\r\nimport { isPointInPolygon, Line } from \"../render/polygon\";\r\nimport { SolarPanelType } from \"../solar\";\r\nimport { intersects, offsetPolygon, PositionedSolarPanel, projectPoint, projectPolygon } from \"./fitting\";\r\n\r\nexport interface MinMax {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n}\r\n\r\nexport function generateGrid(minMax: MinMax, solarPanel: SolarPanelType, horizontal: boolean, anker: Point, rowSpacing: number, columnSpacing: number): Array<Array<PositionedSolarPanel>> {\r\n const grid: Array<Array<PositionedSolarPanel>> = [];\r\n const width = horizontal ? solarPanel.heightMeters : solarPanel.widthMeters;\r\n const widthCount = Math.ceil((minMax.maxX - minMax.minX) / width);\r\n const height = horizontal ? solarPanel.widthMeters : solarPanel.heightMeters;\r\n const heightCount = Math.ceil((minMax.maxY - minMax.minY) / height);\r\n\r\n const widthOffset = width / 2;\r\n const heightOffset = height / 2;\r\n\r\n // calculate the starting point based on the anker\r\n const startX = anker.x - (Math.ceil((anker.x - minMax.minX) / width) * width);\r\n const startY = anker.y - (Math.ceil((anker.y - minMax.minY) / height) * height);\r\n\r\n for (let i = 0; i < heightCount; i++) {\r\n const row: Array<PositionedSolarPanel> = [];\r\n for (let j = 0; j < widthCount; j++) {\r\n const x = startX + j * width + j * columnSpacing + widthOffset;\r\n const y = startY + i * height + i * rowSpacing + heightOffset;\r\n const positionedSolarPanel: PositionedSolarPanel = {\r\n panel: solarPanel,\r\n pixelPosition: {\r\n x: x,\r\n y: y\r\n },\r\n horizontal: horizontal\r\n }\r\n row.push(positionedSolarPanel);\r\n }\r\n grid.push(row);\r\n }\r\n return grid;\r\n}\r\n\r\nfunction getSolarPanelLines(positionedSolarPanel: PositionedSolarPanel, horizontal: boolean): Array<Line> {\r\n const width = horizontal ? positionedSolarPanel.panel.heightMeters : positionedSolarPanel.panel.widthMeters;\r\n const height = horizontal ? positionedSolarPanel.panel.widthMeters : positionedSolarPanel.panel.heightMeters;\r\n const p1 = {\r\n x: positionedSolarPanel.pixelPosition.x - width / 2,\r\n y: positionedSolarPanel.pixelPosition.y - height / 2\r\n }\r\n const p2 = {\r\n x: positionedSolarPanel.pixelPosition.x - width / 2,\r\n y: positionedSolarPanel.pixelPosition.y + height / 2\r\n }\r\n const p3 = {\r\n x: positionedSolarPanel.pixelPosition.x + width / 2,\r\n y: positionedSolarPanel.pixelPosition.y + height / 2\r\n }\r\n const p4 = {\r\n x: positionedSolarPanel.pixelPosition.x + width / 2,\r\n y: positionedSolarPanel.pixelPosition.y - height / 2\r\n }\r\n const lines = [\r\n {\r\n start: p1,\r\n end: p2\r\n },\r\n {\r\n start: p2,\r\n end: p3\r\n },\r\n {\r\n start: p3,\r\n end: p4\r\n },\r\n {\r\n start: p4,\r\n end: p1\r\n }\r\n ]\r\n return lines;\r\n}\r\n\r\n\r\nexport function solarPanelInObstacle(positionedSolarPanel: PositionedSolarPanel, obstacle: Polygon, horizontal: boolean): boolean {\r\n const lines = getSolarPanelLines(positionedSolarPanel, horizontal);\r\n if (isPointInPolygon(positionedSolarPanel.pixelPosition, obstacle)) {\r\n return true;\r\n }\r\n for (let i = 0; i < obstacle.points.length; i++) {\r\n const point = obstacle.points[i];\r\n const nextPoint = obstacle.points[(i + 1) % obstacle.points.length];\r\n const border = {\r\n start: point,\r\n end: nextPoint\r\n }\r\n for (const line of lines) {\r\n if (intersects(line, border)) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function solarPanelInPolygon(positionedSolarPanel: PositionedSolarPanel, polygon: Polygon, horizontal: boolean): boolean {\r\n const lines = getSolarPanelLines(positionedSolarPanel, horizontal);\r\n\r\n for (let i = 0; i < polygon.points.length; i++) {\r\n const point = polygon.points[i];\r\n const nextPoint = polygon.points[(i + 1) % polygon.points.length];\r\n const border = {\r\n start: point,\r\n end: nextPoint\r\n }\r\n for (const line of lines) {\r\n if (intersects(line, border)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return isPointInPolygon(positionedSolarPanel.pixelPosition, polygon);\r\n}\r\n\r\nexport interface Obstacle {\r\n polygon: Polygon;\r\n boundingBox: {\r\n minX: number;\r\n maxX: number;\r\n minY: number;\r\n maxY: number;\r\n }\r\n}\r\n\r\nexport function isPanelObstructed(positionedSolarPanel: PositionedSolarPanel, obstacles: Obstacle[], horizontal: boolean): boolean {\r\n for (const obstacle of obstacles) {\r\n if (solarPanelInObstacle(positionedSolarPanel, obstacle.polygon, horizontal)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nexport function getSolarPanelsInPolygon(grid: Array<Array<PositionedSolarPanel>>, polygon: Polygon, horizontal: boolean, obstacles: Obstacle[]): Array<Array<PositionedSolarPanel>> {\r\n const solarPanels: Array<Array<PositionedSolarPanel>> = [];\r\n for (const row of grid) {\r\n let newRow: Array<PositionedSolarPanel> = [];\r\n for (const positionedSolarPanel of row) {\r\n const isObstructed = isPanelObstructed(positionedSolarPanel, obstacles, horizontal);\r\n if (solarPanelInPolygon(positionedSolarPanel, polygon, horizontal) && !isObstructed) {\r\n newRow.push(positionedSolarPanel);\r\n }\r\n }\r\n solarPanels.push(newRow);\r\n }\r\n return solarPanels;\r\n}\r\n\r\nexport function getOptimalSolarPosition(roof: Polygon, obstacles: Obstacle[], solarPanel: SolarPanelType, angle: number): Array<Array<PositionedSolarPanel>> {\r\n const minX = Math.min(...roof.points.map(p => p.x));\r\n const maxX = Math.max(...roof.points.map(p => p.x));\r\n const minY = Math.min(...roof.points.map(p => p.y));\r\n const maxY = Math.max(...roof.points.map(p => p.y));\r\n const minMax = {\r\n minX: minX,\r\n maxX: maxX,\r\n minY: minY,\r\n maxY: maxY\r\n } as MinMax; \r\n\r\n const horizontalSolarPanel = {\r\n ...solarPanel,\r\n widthMeters: solarPanel.widthMeters * Math.cos(angle * Math.PI / 180),\r\n heightMeters: solarPanel.heightMeters\r\n } as SolarPanelType;\r\n\r\n const verticalSolarPanel = {\r\n ...solarPanel,\r\n widthMeters: solarPanel.widthMeters,\r\n heightMeters: solarPanel.heightMeters * Math.cos(angle * Math.PI / 180)\r\n } as SolarPanelType;\r\n\r\n let solarPanels: Array<Array<PositionedSolarPanel>> = [];\r\n let numberOfPanels = 0;\r\n for (const point of roof.points) {\r\n for (const horizontal of [false]) { // TODO removed true\r\n const grid = generateGrid(minMax, horizontal ? horizontalSolarPanel : verticalSolarPanel, horizontal, point, ROW_SPACING, COLUMN_SPACING);\r\n const solarPanelsInPolygon = getSolarPanelsInPolygon(grid, roof, horizontal, obstacles);\r\n\r\n const numberOfPanelsInPolygon = solarPanelsInPolygon.reduce((acc, row) => acc + row.length, 0);\r\n if (numberOfPanelsInPolygon > numberOfPanels) {\r\n numberOfPanels = numberOfPanelsInPolygon;\r\n solarPanels = solarPanelsInPolygon;\r\n }\r\n }\r\n break;\r\n }\r\n return solarPanels;\r\n}\r\n\r\nfunction projectObstacles(obstacles: Polygon[], azimuth: number, offset: {x: number, y: number}, inset: number): Array<Obstacle> {\r\n const result: Array<Obstacle> = [];\r\n for (const obstacle of obstacles) {\r\n const offsetObstacle = offsetPolygon(obstacle, offset);\r\n const projectedObstacle = projectPolygon(offsetObstacle.polygon, -azimuth);\r\n const insetObstacle = insetPolygon(projectedObstacle, -inset);\r\n\r\n const minX = Math.min(...insetObstacle.points.map(p => p.x));\r\n const maxX = Math.max(...insetObstacle.points.map(p => p.x));\r\n const minY = Math.min(...insetObstacle.points.map(p => p.y));\r\n const maxY = Math.max(...insetObstacle.points.map(p => p.y));\r\n const boundingBox = {\r\n minX: minX,\r\n maxX: maxX,\r\n minY: minY,\r\n maxY: maxY\r\n } as MinMax;\r\n result.push({\r\n polygon: projectedObstacle,\r\n boundingBox: boundingBox\r\n });\r\n }\r\n return result;\r\n}\r\n\r\nfunction isClockwise(points: Point[]): boolean {\r\n let sum = 0;\r\n for (let i = 0; i < points.length; i++) {\r\n const curr = points[i];\r\n const next = points[(i + 1) % points.length];\r\n sum += (next.x - curr.x) * (next.y + curr.y);\r\n }\r\n return sum > 0;\r\n}\r\n\r\nexport function insetPolygon(polygon: Polygon, inset: number): Polygon {\r\n const points = polygon.points;\r\n const isClockwisePolygon = isClockwise(points);\r\n inset = inset * Math.sqrt(2) * (isClockwisePolygon ? -1 : 1);\r\n const insetPoints: Point[] = [];\r\n \r\n for (let i = 0; i < points.length; i++) {\r\n const prev = points[(i - 1 + points.length) % points.length];\r\n const curr = points[i];\r\n const next = points[(i + 1) % points.length];\r\n \r\n // Calculate vectors for the two edges meeting at current point\r\n const v1 = {\r\n x: curr.x - prev.x,\r\n y: curr.y - prev.y\r\n };\r\n const v2 = {\r\n x: next.x - curr.x,\r\n y: next.y - curr.y\r\n };\r\n \r\n // Calculate perpendicular vectors (90 degrees clockwise)\r\n const perp1 = {\r\n x: -v1.y,\r\n y: v1.x\r\n };\r\n const perp2 = {\r\n x: -v2.y,\r\n y: v2.x\r\n };\r\n \r\n // Normalize the perpendicular vectors\r\n const length1 = Math.sqrt(perp1.x * perp1.x + perp1.y * perp1.y);\r\n const length2 = Math.sqrt(perp2.x * perp2.x + perp2.y * perp2.y);\r\n \r\n perp1.x /= length1;\r\n perp1.y /= length1;\r\n perp2.x /= length2;\r\n perp2.y /= length2;\r\n \r\n // Calculate the bisector vector\r\n const bisector = {\r\n x: perp1.x + perp2.x,\r\n y: perp1.y + perp2.y\r\n };\r\n \r\n // Normalize the bisector\r\n const bisectorLength = Math.sqrt(bisector.x * bisector.x + bisector.y * bisector.y);\r\n bisector.x /= bisectorLength;\r\n bisector.y /= bisectorLength;\r\n \r\n // Calculate the inset point\r\n const insetPoint = {\r\n x: curr.x + bisector.x * inset,\r\n y: curr.y + bisector.y * inset\r\n };\r\n \r\n insetPoints.push(insetPoint);\r\n }\r\n \r\n return {\r\n points: insetPoints,\r\n type: polygon.type,\r\n closed: polygon.closed,\r\n _id: polygon._id,\r\n details: polygon.details\r\n };\r\n}\r\n\r\nexport function getOptimalSolarPositionFully(roof: Polygon, obstacles: Polygon[], solarPanel: SolarPanelType, azimuth: number, inset: number, angle: number): Array<PositionedSolarPanel> {\r\n const insetRoof = insetPolygon(roof, inset);\r\n const offset = offsetPolygon(insetRoof);\r\n const projectedOffset = projectPolygon(offset.polygon, -azimuth);\r\n\r\n const projectedObstacles = projectObstacles(obstacles, azimuth, offset.offset, inset);\r\n\r\n const horizontalSolarPanels = getOptimalSolarPosition(projectedOffset, projectedObstacles, solarPanel, angle);\r\n const unprojectedPanels: Array<PositionedSolarPanel> = [];\r\n\r\n for (const panel of horizontalSolarPanels.flat()) {\r\n const unprojectedPanel = projectPoint(panel.pixelPosition, azimuth);\r\n const offsetPosition = {\r\n x: unprojectedPanel.x + offset.offset.x,\r\n y: unprojectedPanel.y + offset.offset.y\r\n }\r\n unprojectedPanels.push({\r\n panel: panel.panel,\r\n pixelPosition: offsetPosition,\r\n horizontal: panel.horizontal\r\n });\r\n }\r\n return unprojectedPanels;\r\n}","/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-800: oklch(27.8% 0.033 256.848);\n --color-black: #000;\n --spacing: 0.25rem;\n --container-md: 28rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --radius-lg: 0.5rem;\n --radius-4xl: 2rem;\n --animate-spin: spin 1s linear infinite;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n --color-primary: hsl(41 51% 90%);\n --color-primary-foreground: hsl(0 0% 0%);\n --color-secondary: hsl(28 100% 8%);\n --color-secondary-foreground: hsl(0 0% 100%);\n --color-tertiary: hsl(28 100% 29%);\n --color-tertiary-foreground: hsl(0 0% 100%);\n --color-muted: hsl(0 0% 100%);\n --color-muted-foreground: hsl(0 0% 0%);\n --color-error: hsl(0 100% 50%);\n --color-error-foreground: hsl(0 0% 100%);\n --color-surface: hsl(0 0% 88%);\n --color-surface-hover: hsl(0 0% 82%);\n --color-surface-active: hsl(0 0% 64%);\n --color-text-muted: hsl(0 0% 45%);\n --color-text-secondary: hsl(0 0% 55%);\n --color-text-placeholder: hsl(0 0% 73%);\n --color-border: hsl(0 0% 82%);\n --color-border-light: hsl(0 0% 93%);\n --color-success: hsl(142 76% 36%);\n --color-info: hsl(221 83% 53%);\n --color-hover: hsl(0 0% 88%);\n --color-hover-dark: hsl(28 100% 8%);\n --color-overlay: rgba(0, 0, 0, 0.24);\n --color-tooltip: hsl(0 0% 13%);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=\"until-found\"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-none {\n pointer-events: none;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-3 {\n left: calc(var(--spacing) * 3);\n }\n .z-20 {\n z-index: 20;\n }\n .z-50 {\n z-index: 50;\n }\n .m-auto {\n margin: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-4 {\n margin-top: calc(var(--spacing) * 4);\n }\n .mt-6 {\n margin-top: calc(var(--spacing) * 6);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .block {\n display: block;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .inline-flex {\n display: inline-flex;\n }\n .h-4 {\n height: calc(var(--spacing) * 4);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-16 {\n height: calc(var(--spacing) * 16);\n }\n .h-48 {\n height: calc(var(--spacing) * 48);\n }\n .h-\\[400px\\] {\n height: 400px;\n }\n .h-full {\n height: 100%;\n }\n .w-4 {\n width: calc(var(--spacing) * 4);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-16 {\n width: calc(var(--spacing) * 16);\n }\n .w-64 {\n width: calc(var(--spacing) * 64);\n }\n .w-full {\n width: 100%;\n }\n .max-w-md {\n max-width: var(--container-md);\n }\n .flex-1 {\n flex: 1;\n }\n .flex-3 {\n flex: 3;\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-help {\n cursor: help;\n }\n .appearance-none {\n appearance: none;\n }\n .grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n .grid-rows-2 {\n grid-template-rows: repeat(2, minmax(0, 1fr));\n }\n .grid-rows-3 {\n grid-template-rows: repeat(3, minmax(0, 1fr));\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-row {\n flex-direction: row;\n }\n .flex-wrap {\n flex-wrap: wrap;\n }\n .items-center {\n align-items: center;\n }\n .items-start {\n align-items: flex-start;\n }\n .items-stretch {\n align-items: stretch;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .justify-start {\n justify-content: flex-start;\n }\n .gap-0 {\n gap: calc(var(--spacing) * 0);\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .space-y-4 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-6 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-4xl {\n border-radius: var(--radius-4xl);\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t-2 {\n border-top-style: var(--tw-border-style);\n border-top-width: 2px;\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-border {\n border-color: var(--color-border);\n }\n .border-error {\n border-color: var(--color-error);\n }\n .border-gray-300 {\n border-color: var(--color-gray-300);\n }\n .border-secondary {\n border-color: var(--color-secondary);\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-gray-800 {\n background-color: var(--color-gray-800);\n }\n .bg-muted {\n background-color: var(--color-muted);\n }\n .bg-overlay {\n background-color: var(--color-overlay);\n }\n .bg-primary {\n background-color: var(--color-primary);\n }\n .bg-secondary {\n background-color: var(--color-secondary);\n }\n .bg-surface {\n background-color: var(--color-surface);\n }\n .bg-surface-active {\n background-color: var(--color-surface-active);\n }\n .bg-text-secondary {\n background-color: var(--color-text-secondary);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .p-1 {\n padding: calc(var(--spacing) * 1);\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-3 {\n padding: calc(var(--spacing) * 3);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .pt-2 {\n padding-top: calc(var(--spacing) * 2);\n }\n .pt-4 {\n padding-top: calc(var(--spacing) * 4);\n }\n .pt-7 {\n padding-top: calc(var(--spacing) * 7);\n }\n .pr-4 {\n padding-right: calc(var(--spacing) * 4);\n }\n .pb-3 {\n padding-bottom: calc(var(--spacing) * 3);\n }\n .pb-4 {\n padding-bottom: calc(var(--spacing) * 4);\n }\n .pl-2 {\n padding-left: calc(var(--spacing) * 2);\n }\n .pl-4 {\n padding-left: calc(var(--spacing) * 4);\n }\n .pl-10 {\n padding-left: calc(var(--spacing) * 10);\n }\n .text-center {\n text-align: center;\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .text-error {\n color: var(--color-error);\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-muted {\n color: var(--color-muted);\n }\n .text-muted-foreground {\n color: var(--color-muted-foreground);\n }\n .text-primary-foreground {\n color: var(--color-primary-foreground);\n }\n .text-secondary {\n color: var(--color-secondary);\n }\n .text-secondary-foreground {\n color: var(--color-secondary-foreground);\n }\n .text-success {\n color: var(--color-success);\n }\n .text-text-muted {\n color: var(--color-text-muted);\n }\n .text-text-placeholder {\n color: var(--color-text-placeholder);\n }\n .text-text-secondary {\n color: var(--color-text-secondary);\n }\n .accent-tertiary {\n accent-color: var(--color-tertiary);\n }\n .opacity-0 {\n opacity: 0%;\n }\n .shadow {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .group-hover\\:opacity-100 {\n &:is(:where(.group):hover *) {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n }\n .hover\\:bg-hover {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-hover);\n }\n }\n }\n .hover\\:bg-hover-dark {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-hover-dark);\n }\n }\n }\n .hover\\:bg-muted {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-muted);\n }\n }\n }\n .hover\\:bg-overlay {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-overlay);\n }\n }\n }\n .hover\\:bg-secondary {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-secondary);\n }\n }\n }\n .hover\\:bg-secondary\\/80 {\n &:hover {\n @media (hover: hover) {\n background-color: color-mix(in srgb, hsl(28 100% 8%) 80%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-secondary) 80%, transparent);\n }\n }\n }\n }\n .hover\\:bg-surface-hover {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-surface-hover);\n }\n }\n }\n .hover\\:bg-tertiary {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-tertiary);\n }\n }\n }\n .hover\\:bg-text-secondary {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-text-secondary);\n }\n }\n }\n .hover\\:text-muted {\n &:hover {\n @media (hover: hover) {\n color: var(--color-muted);\n }\n }\n }\n .focus\\:border-transparent {\n &:focus {\n border-color: transparent;\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-info {\n &:focus {\n --tw-ring-color: var(--color-info);\n }\n }\n .focus\\:ring-secondary {\n &:focus {\n --tw-ring-color: var(--color-secondary);\n }\n }\n .focus\\:ring-tertiary {\n &:focus {\n --tw-ring-color: var(--color-tertiary);\n }\n }\n .focus\\:ring-offset-0 {\n &:focus {\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .lg\\:gap-4 {\n @media (width >= 64rem) {\n gap: calc(var(--spacing) * 4);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:rounded-full {\n &::-webkit-slider-runnable-track {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:bg-black\\/25 {\n &::-webkit-slider-runnable-track {\n background-color: color-mix(in srgb, #000 25%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 25%, transparent);\n }\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:h-\\[10px\\] {\n &::-webkit-slider-thumb {\n height: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:w-\\[10px\\] {\n &::-webkit-slider-thumb {\n width: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:appearance-none {\n &::-webkit-slider-thumb {\n appearance: none;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:rounded-full {\n &::-webkit-slider-thumb {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:bg-muted {\n &::-webkit-slider-thumb {\n background-color: var(--color-muted);\n }\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-space-y-reverse {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-space-y-reverse: 0;\n --tw-border-style: solid;\n --tw-font-weight: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-duration: initial;\n }\n }\n}\n","import {\r\n Component,\r\n Element,\r\n h,\r\n Listen,\r\n Prop,\r\n State,\r\n Watch,\r\n} from \"@stencil/core\";\r\n\r\nimport {\r\n renderCombinedWithZoom,\r\n renderSolarPanel,\r\n} from \"../../utils/visualize\";\r\nimport {\r\n BuildingInsightsResponse,\r\n GeoTiff,\r\n SolarPanelType,\r\n} from \"../../utils/solar\";\r\nimport { fetchSolarData, getBuildingImages } from \"../../utils/api\";\r\nimport { drawPolygon, isPointInPolygon } from \"../../utils/render/polygon\";\r\nimport { projectPointPerpendicularToLine } from \"../../utils/render/projection\";\r\nimport { Point, Polygon, SelectedPolygon } from \"../../types/shapes\";\r\nimport {\r\n deleteTool,\r\n markRoofEdgeTool,\r\n moveTool,\r\n obstructionTool,\r\n roofTool,\r\n Tool,\r\n tools,\r\n} from \"../../utils/render/tools\";\r\nimport {\r\n DEFAULT_SOLAR_EXPERT_CONFIG,\r\n DEFAULT_SOLAR_PANEL_TYPE,\r\n SolarExpertConfig,\r\n} from \"../../config\";\r\nimport { getFillColor } from \"../../utils/render/color\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\nimport { calculatePolygonArea, getPixelInMeters } from \"../../utils/utils\";\r\nimport {\r\n getBestFittingRoofSegment,\r\n SolarPanelSystemPart,\r\n} from \"../../utils/geometry/fitting\";\r\nimport { getOptimalSolarPositionFully } from \"../../utils/geometry/gridMatch\";\r\nimport { BORDER_INSET, DEFAULT_SUNNINESS } from \"../../constants\";\r\nimport { getLanguageStrings } from \"../../utils/lang/general\";\r\nimport { onChange, Settings, state } from \"../../store\";\r\n\r\n@Component({\r\n tag: \"map-draw\",\r\n styleUrl: \"../../output.css\",\r\n shadow: false,\r\n})\r\nexport class MapDraw {\r\n @Prop()\r\n apiKey: string = \"\";\r\n @Prop()\r\n config: SolarExpertConfig = DEFAULT_SOLAR_EXPERT_CONFIG;\r\n @Prop()\r\n solarPanel: SolarPanelType = DEFAULT_SOLAR_PANEL_TYPE;\r\n\r\n @State()\r\n showInstructions: boolean = true;\r\n @State()\r\n showSettings: boolean = false;\r\n @State()\r\n zoom: number = 1;\r\n @State()\r\n loadingState: \"empty\" | \"loading\" | \"loaded\" = \"empty\";\r\n @State()\r\n rgbTiff: GeoTiff | null = null;\r\n @State()\r\n draggedPointIndex: number | null = null;\r\n @State()\r\n hoveredPointIndex: number | null = null;\r\n @State()\r\n hoveredPolygon: SelectedPolygon | null = null;\r\n @State()\r\n shiftKeyPressed: boolean = false;\r\n @State()\r\n altKeyPressed: boolean = false;\r\n @State()\r\n mousePoint: Point | null = null;\r\n @State()\r\n currentTool: Tool = roofTool;\r\n @State()\r\n roofPolygons: { [id: string]: Polygon } = {};\r\n @State()\r\n roofPolygonsSolarPanels: { [id: string]: SolarPanelSystemPart } = {};\r\n @State()\r\n obstructionPolygons: { [id: string]: Polygon } = {};\r\n @State()\r\n selectedPolygon: SelectedPolygon | null = null;\r\n @State()\r\n buildingInsights: BuildingInsightsResponse | null = null;\r\n @State()\r\n pixelInMeters: number = 0.2;\r\n @State()\r\n isMobile: boolean = false;\r\n @State()\r\n highlightedEdge: { pointA: Point; pointB: Point } | null = null;\r\n\r\n @Element()\r\n el: HTMLElement;\r\n private canvasElement?: HTMLCanvasElement;\r\n private polygonCanvas?: HTMLCanvasElement;\r\n private polygonCtx?: CanvasRenderingContext2D;\r\n\r\n private getCurrentPolygon(): Polygon | null {\r\n if (!this.selectedPolygon) {\r\n return null;\r\n }\r\n const { _id, type } = this.selectedPolygon;\r\n return type === \"roof\"\r\n ? this.roofPolygons[_id]\r\n : this.obstructionPolygons[_id];\r\n }\r\n\r\n componentWillLoad() {\r\n onChange(\"latitude\", () => {\r\n this.getBuildingImages();\r\n this.getBuildingInsights();\r\n });\r\n onChange(\"longitude\", () => {\r\n this.getBuildingImages();\r\n this.getBuildingInsights();\r\n });\r\n }\r\n\r\n componentDidLoad() {\r\n if (state.latitude && state.longitude) {\r\n this.loadingState = \"loading\";\r\n this.getBuildingInsights();\r\n this.getBuildingImages();\r\n }\r\n\r\n requestAnimationFrame(() => {\r\n if (this.canvasElement) {\r\n const rect = this.canvasElement.getBoundingClientRect();\r\n this.canvasElement.width = rect.width;\r\n this.canvasElement.height = rect.height;\r\n this.drawMap();\r\n }\r\n });\r\n }\r\n\r\n private sizeCanvas(width: number, height: number) {\r\n if (this.canvasElement) {\r\n this.canvasElement.width = width;\r\n this.canvasElement.height = height;\r\n }\r\n if (this.polygonCanvas) {\r\n this.polygonCanvas.width = width;\r\n this.polygonCanvas.height = height;\r\n this.polygonCtx = this.polygonCanvas.getContext(\"2d\");\r\n }\r\n }\r\n\r\n async getBuildingInsights() {\r\n if (!state.latitude || !state.longitude) {\r\n return;\r\n }\r\n this.loadingState = \"loading\";\r\n\r\n if (this.buildingInsights) {\r\n const sameLocation =\r\n this.buildingInsights.center.latitude === state.latitude &&\r\n this.buildingInsights.center.longitude === state.longitude;\r\n if (sameLocation) {\r\n return;\r\n }\r\n this.obstructionPolygons = {};\r\n this.roofPolygons = {};\r\n this.selectedPolygon = null;\r\n this.hoveredPolygon = null;\r\n this.canvasElement.getContext(\"2d\")?.clearRect(\r\n 0,\r\n 0,\r\n this.canvasElement.width,\r\n this.canvasElement.height,\r\n );\r\n this.polygonCtx?.clearRect(\r\n 0,\r\n 0,\r\n this.polygonCanvas.width,\r\n this.polygonCanvas.height,\r\n );\r\n this.rgbTiff = null;\r\n }\r\n this.buildingInsights = await fetchSolarData(\r\n state.latitude,\r\n state.longitude,\r\n this.apiKey,\r\n );\r\n if (!this.buildingInsights) {\r\n alert(\"No building insights found. Please enter them manually.\");\r\n }\r\n\r\n // If on mobile, automatically calculate panels using Google API data\r\n if (state.isMobile && this.buildingInsights) {\r\n const maxPanels =\r\n this.buildingInsights.solarPotential.maxArrayPanelsCount;\r\n const approximatedPanels = Math.floor(maxPanels * 3 / 4); // Use two thirds of max panels\r\n\r\n const positionedPanels = Array(approximatedPanels).fill(null)\r\n .map((_, __) => ({\r\n panel: this.solarPanel,\r\n pixelPosition: {\r\n x: -1,\r\n y: -1,\r\n },\r\n horizontal: true,\r\n rotation: 0,\r\n }));\r\n\r\n this.roofPolygonsSolarPanels = {\r\n ...this.roofPolygonsSolarPanels,\r\n [\"mobile-panels\"]: {\r\n positionedPanels,\r\n sunniness:\r\n this.buildingInsights.solarPotential.buildingStats\r\n .sunshineQuantiles[5] ?? DEFAULT_SUNNINESS,\r\n },\r\n };\r\n }\r\n }\r\n\r\n async getBuildingImages() {\r\n if (!state.latitude || !state.longitude) {\r\n return;\r\n }\r\n if (this.buildingInsights) {\r\n const sameLocation =\r\n this.buildingInsights.center.latitude === state.latitude &&\r\n this.buildingInsights.center.longitude === state.longitude;\r\n if (sameLocation) {\r\n return;\r\n }\r\n }\r\n this.rgbTiff = await getBuildingImages(\r\n state.latitude,\r\n state.longitude,\r\n this.apiKey,\r\n state.radiusMeters,\r\n );\r\n this.pixelInMeters = getPixelInMeters(this.rgbTiff);\r\n this.loadingState = \"loaded\";\r\n }\r\n\r\n private convertToCanvasCoordinates(event: MouseEvent): Point {\r\n const rect = this.polygonCanvas.getBoundingClientRect();\r\n const siteX = event.clientX - rect.left;\r\n const siteY = event.clientY - rect.top;\r\n return {\r\n x: siteX / (rect.right - rect.left) * this.canvasElement.width,\r\n y: siteY / (rect.bottom - rect.top) * this.canvasElement.height,\r\n };\r\n }\r\n\r\n @Watch(\"rgbTiff\")\r\n @Watch(\"buildingInsights\")\r\n @Watch(\"canvasElement\")\r\n async drawMap() {\r\n if (\r\n !this.canvasElement || !this.rgbTiff || !this.buildingInsights\r\n ) return;\r\n\r\n this.sizeCanvas(this.rgbTiff.width, this.rgbTiff.height);\r\n\r\n renderCombinedWithZoom({\r\n rgb: this.rgbTiff,\r\n zoom: this.zoom,\r\n canvas: this.canvasElement,\r\n });\r\n }\r\n\r\n @Listen(\"mousemove\", { target: \"document\" })\r\n handleMouseMove(event: MouseEvent) {\r\n if (state.isMobile) return; // Prevent interactions on mobile\r\n if (!this.polygonCanvas || !this.polygonCtx) return;\r\n\r\n // translate the website pixel coordinates to the canvas coordinates\r\n const { x, y } = this.convertToCanvasCoordinates(event);\r\n this.mousePoint = { x, y };\r\n\r\n const currentPolygon = this.getCurrentPolygon();\r\n let redraw = false;\r\n\r\n if (this.currentTool.name === \"markRoofEdge\") {\r\n let distances = [];\r\n for (let i = 0; i < currentPolygon?.points.length; i++) {\r\n const pointA = currentPolygon?.points[i];\r\n const pointB = currentPolygon\r\n ?.points[(i + 1) % currentPolygon?.points.length];\r\n const distanceA = Math.sqrt(\r\n Math.pow(x - pointA.x, 2) + Math.pow(y - pointA.y, 2),\r\n );\r\n const distanceB = Math.sqrt(\r\n Math.pow(x - pointB.x, 2) + Math.pow(y - pointB.y, 2),\r\n );\r\n const edgeLength = Math.sqrt(\r\n Math.pow(pointA.x - pointB.x, 2) +\r\n Math.pow(pointA.y - pointB.y, 2),\r\n );\r\n distances.push({\r\n dist: distanceA + distanceB - edgeLength,\r\n edge: { pointA, pointB },\r\n });\r\n }\r\n const closestEdge = distances.sort((a, b) => a.dist - b.dist)[0];\r\n if (closestEdge && (closestEdge.dist < 10)) {\r\n this.highlightedEdge = closestEdge.edge;\r\n redraw = true;\r\n } else if (this.highlightedEdge) {\r\n this.highlightedEdge = null;\r\n redraw = true;\r\n }\r\n }\r\n\r\n // Check for point hover\r\n const newHoveredPointIndex = currentPolygon?.points.findIndex(\r\n (point) => {\r\n const distance = Math.sqrt(\r\n Math.pow(x - point.x, 2) + Math.pow(y - point.y, 2),\r\n );\r\n return distance < 10;\r\n },\r\n );\r\n\r\n // Check for polygon hover\r\n let newHoveredPolygon = null;\r\n for (const polygon of Object.values(this.obstructionPolygons)) {\r\n if (isPointInPolygon({ x, y }, polygon)) {\r\n newHoveredPolygon = { _id: polygon._id, type: \"obstruction\" };\r\n break;\r\n }\r\n }\r\n // obstruction polygons get priority\r\n if (!newHoveredPolygon) {\r\n for (const polygon of Object.values(this.roofPolygons)) {\r\n if (isPointInPolygon({ x, y }, polygon)) {\r\n newHoveredPolygon = { _id: polygon._id, type: \"roof\" };\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // Only redraw if hover state changed\r\n if (\r\n this.hoveredPolygon ||\r\n newHoveredPointIndex !== this.hoveredPointIndex ||\r\n JSON.stringify(newHoveredPolygon) !==\r\n JSON.stringify(this.hoveredPolygon)\r\n ) {\r\n this.hoveredPointIndex = newHoveredPointIndex;\r\n this.hoveredPolygon = newHoveredPolygon;\r\n redraw = true;\r\n }\r\n\r\n // Handle dragging\r\n if (\r\n this.draggedPointIndex !== null && currentPolygon &&\r\n this.currentTool.name === \"move\"\r\n ) {\r\n currentPolygon.points[this.draggedPointIndex] = { x, y };\r\n // Recalculate area if this is a roof polygon\r\n if (currentPolygon.type === \"roof\" && currentPolygon.closed) {\r\n const metersInPixels = 1 / this.pixelInMeters;\r\n const area = calculatePolygonArea(currentPolygon.points) /\r\n (metersInPixels * metersInPixels);\r\n currentPolygon.details.area = area;\r\n }\r\n redraw = true;\r\n }\r\n\r\n if (this.shiftKeyPressed) {\r\n redraw = true;\r\n }\r\n\r\n if (redraw) {\r\n this.drawPolygons();\r\n }\r\n }\r\n\r\n private drawPolygons() {\r\n if (!this.polygonCanvas || !this.polygonCtx) return;\r\n\r\n // Clear the canvas and redraw the map\r\n this.polygonCtx.clearRect(\r\n 0,\r\n 0,\r\n this.polygonCanvas.width,\r\n this.polygonCanvas.height,\r\n );\r\n\r\n // draw roof polygons\r\n for (const polygon of Object.values(this.roofPolygons)) {\r\n const fillColor = getFillColor(\r\n this.selectedPolygon,\r\n this.hoveredPolygon,\r\n polygon._id,\r\n polygon,\r\n this.config,\r\n );\r\n\r\n drawPolygon({\r\n polygonCtx: this.polygonCtx,\r\n polygonCanvas: this.polygonCanvas,\r\n polygon,\r\n strokeColor: polygon.closed\r\n ? this.config.closedRoofColor\r\n : this.config.openRoofColor,\r\n fillColor,\r\n pixelInMeters: this.pixelInMeters,\r\n shiftKeyPressed: this.shiftKeyPressed,\r\n mousePoint: this.mousePoint,\r\n highlightColor: this.config.highlightColor,\r\n highlightedEdge: this.highlightedEdge,\r\n });\r\n\r\n const solarPanels = this.roofPolygonsSolarPanels[polygon._id];\r\n const convertedSolarPanel: SolarPanelType = {\r\n ...this.solarPanel,\r\n widthMeters: this.solarPanel.widthMeters / this.pixelInMeters,\r\n heightMeters: this.solarPanel.heightMeters / this.pixelInMeters,\r\n };\r\n if (solarPanels) {\r\n for (const panel of solarPanels.positionedPanels) {\r\n renderSolarPanel(\r\n panel,\r\n this.polygonCtx,\r\n convertedSolarPanel.widthMeters,\r\n convertedSolarPanel.heightMeters,\r\n polygon.details?.azimuth,\r\n polygon.details?.pitch,\r\n );\r\n }\r\n }\r\n }\r\n\r\n // draw obstruction polygons\r\n for (const polygon of Object.values(this.obstructionPolygons)) {\r\n const fillColor = getFillColor(\r\n this.selectedPolygon,\r\n this.hoveredPolygon,\r\n polygon._id,\r\n polygon,\r\n this.config,\r\n );\r\n\r\n drawPolygon({\r\n polygonCtx: this.polygonCtx,\r\n polygonCanvas: this.polygonCanvas,\r\n polygon,\r\n pixelInMeters: this.pixelInMeters,\r\n shiftKeyPressed: this.shiftKeyPressed,\r\n mousePoint: this.mousePoint,\r\n strokeColor: polygon.closed\r\n ? this.config.closedObstructionColor\r\n : this.config.openObstructionColor,\r\n fillColor,\r\n highlightColor: this.config.highlightColor,\r\n });\r\n }\r\n }\r\n\r\n private deletePolygon(_id: string) {\r\n if (this.selectedPolygon?._id === _id) {\r\n this.selectedPolygon = null;\r\n }\r\n if (this.roofPolygons[_id]) {\r\n delete this.roofPolygons[_id];\r\n delete this.roofPolygonsSolarPanels[_id];\r\n }\r\n if (this.obstructionPolygons[_id]) {\r\n delete this.obstructionPolygons[_id];\r\n }\r\n }\r\n\r\n @Listen(\"keydown\", { target: \"document\" })\r\n handleKeyDown(event: KeyboardEvent) {\r\n if (event.target instanceof HTMLInputElement) {\r\n return;\r\n }\r\n // Handle shift key for perpendicular points\r\n if (event.shiftKey && !this.shiftKeyPressed) {\r\n this.shiftKeyPressed = true;\r\n this.drawPolygons();\r\n return;\r\n }\r\n if (event.altKey && !this.altKeyPressed) {\r\n this.altKeyPressed = true;\r\n return;\r\n }\r\n if (\r\n (event.key === \"Delete\" || event.key === \"Backspace\") &&\r\n this.selectedPolygon\r\n ) {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (currentPolygon.closed) {\r\n this.deletePolygon(currentPolygon._id);\r\n this.drawPolygons();\r\n return;\r\n }\r\n currentPolygon.points.pop();\r\n this.drawPolygons();\r\n return;\r\n }\r\n\r\n // Handle tool selection shortcuts\r\n const pressedKey = event.key.toLowerCase();\r\n const tool = tools.find((t) =>\r\n t.keyboardShortcut?.toLowerCase() === pressedKey\r\n );\r\n if (tool) {\r\n this.currentTool = tool;\r\n }\r\n }\r\n\r\n @Listen(\"keyup\", { target: \"document\" })\r\n handleKeyUp(event: KeyboardEvent) {\r\n if (!event.shiftKey && this.shiftKeyPressed) {\r\n this.shiftKeyPressed = false;\r\n this.drawPolygons();\r\n }\r\n if (!event.altKey && this.altKeyPressed) {\r\n this.altKeyPressed = false;\r\n }\r\n }\r\n\r\n private undo() {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (!currentPolygon) {\r\n return;\r\n }\r\n if (currentPolygon.closed) {\r\n currentPolygon.closed = false;\r\n if (currentPolygon.type === \"roof\") {\r\n delete this.roofPolygonsSolarPanels[currentPolygon._id];\r\n this.currentTool = roofTool;\r\n this.highlightedEdge = null;\r\n } else if (currentPolygon.type === \"obstruction\") {\r\n this.currentTool = obstructionTool;\r\n }\r\n } else {\r\n currentPolygon.points.pop();\r\n }\r\n this.drawPolygons();\r\n }\r\n\r\n @Listen(\"mousedown\", { target: \"document\" })\r\n handleMouseDown(event: MouseEvent) {\r\n if (this.currentTool.name === \"undo\") {\r\n return;\r\n }\r\n if (state.isMobile) return; // Prevent interactions on mobile\r\n if (!this.polygonCanvas || !this.polygonCtx) return;\r\n if (!this.polygonCanvas.contains(event.target as Node)) return;\r\n\r\n let { x, y } = this.convertToCanvasCoordinates(event);\r\n\r\n if (this.currentTool.name === \"markRoofEdge\") {\r\n if (!this.highlightedEdge) {\r\n return;\r\n }\r\n const x = this.highlightedEdge.pointA.x -\r\n this.highlightedEdge.pointB.x;\r\n const y = this.highlightedEdge.pointA.y -\r\n this.highlightedEdge.pointB.y;\r\n const azimuth = Math.atan2(-x, y) * (180 / Math.PI);\r\n this.calculateSolarPanels();\r\n this.handleAzimuthChange({\r\n target: {\r\n value: azimuth,\r\n },\r\n } as unknown as Event);\r\n return;\r\n }\r\n if (this.currentTool.name === \"delete\") {\r\n if (!this.hoveredPolygon) {\r\n return;\r\n }\r\n const { _id, type } = this.hoveredPolygon;\r\n if (type === \"roof\") {\r\n delete this.roofPolygons[_id];\r\n delete this.roofPolygonsSolarPanels[_id];\r\n } else if (type === \"obstruction\") {\r\n delete this.obstructionPolygons[_id];\r\n }\r\n this.hoveredPolygon = null;\r\n if (this.selectedPolygon?._id === _id) {\r\n this.selectedPolygon = null;\r\n }\r\n this.drawPolygons();\r\n return;\r\n }\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (this.currentTool.name === \"move\") {\r\n // Check if we're clicking on a point of the selected polygon\r\n if (this.selectedPolygon) {\r\n const pointIndex = currentPolygon?.points.findIndex((point) => {\r\n const distance = Math.sqrt(\r\n Math.pow(x - point.x, 2) + Math.pow(y - point.y, 2),\r\n );\r\n return distance < 10;\r\n });\r\n if (pointIndex !== undefined && pointIndex !== -1) {\r\n this.draggedPointIndex = pointIndex;\r\n return;\r\n }\r\n\r\n if (this.hoveredPolygon) {\r\n this.selectedPolygon = this.hoveredPolygon;\r\n return;\r\n }\r\n }\r\n this.selectedPolygon = null;\r\n this.drawPolygons();\r\n return;\r\n }\r\n if (\r\n !this.selectedPolygon || currentPolygon?.closed ||\r\n this.currentTool.name !== this.selectedPolygon?.type\r\n ) {\r\n // no polygon is active, create a new one\r\n const newPolygon: Polygon = {\r\n _id: uuidv4(),\r\n points: [{ x, y }],\r\n type: this.currentTool.name,\r\n closed: false,\r\n };\r\n let _id;\r\n if (this.currentTool.name === \"roof\") {\r\n this.roofPolygons = {\r\n ...this.roofPolygons,\r\n [newPolygon._id]: newPolygon,\r\n };\r\n _id = newPolygon._id;\r\n } else if (this.currentTool.name === \"obstruction\") {\r\n this.obstructionPolygons = {\r\n ...this.obstructionPolygons,\r\n [newPolygon._id]: newPolygon,\r\n };\r\n _id = newPolygon._id;\r\n }\r\n this.selectedPolygon = { _id, type: this.currentTool.name };\r\n this.drawPolygons();\r\n return;\r\n }\r\n\r\n if (currentPolygon.closed) {\r\n return;\r\n }\r\n\r\n // If we have at least one point, check if we're clicking near the first point\r\n if (currentPolygon.points.length > 2) {\r\n const firstPoint = currentPolygon.points[0];\r\n const distance = Math.sqrt(\r\n Math.pow(x - firstPoint.x, 2) + Math.pow(y - firstPoint.y, 2),\r\n );\r\n\r\n if (distance < 10) {\r\n this.closePolygon();\r\n return;\r\n }\r\n }\r\n\r\n // Handle shift key for perpendicular points\r\n if (event.shiftKey && currentPolygon?.points.length >= 2) {\r\n const projectedPoint = projectPointPerpendicularToLine({\r\n x,\r\n y,\r\n lastPoint:\r\n currentPolygon.points[currentPolygon.points.length - 1],\r\n secondLastPoint:\r\n currentPolygon.points[currentPolygon.points.length - 2],\r\n });\r\n x = projectedPoint.x;\r\n y = projectedPoint.y;\r\n }\r\n\r\n currentPolygon.points = [...currentPolygon.points, { x, y }];\r\n this.drawPolygons();\r\n }\r\n\r\n @Listen(\"mouseup\", { target: \"document\" })\r\n handleMouseUp() {\r\n this.draggedPointIndex = null;\r\n }\r\n\r\n private closePolygon() {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (\r\n currentPolygon.points.length >= 3 &&\r\n (this.currentTool.name === \"roof\" ||\r\n this.currentTool.name === \"obstruction\")\r\n ) {\r\n currentPolygon.closed = true;\r\n }\r\n\r\n if (currentPolygon.type === \"roof\") {\r\n // Calculate basic polygon details\r\n const metersInPixels = 1 / this.pixelInMeters;\r\n const area = calculatePolygonArea(currentPolygon.points) /\r\n (metersInPixels * metersInPixels);\r\n const bestMatch = getBestFittingRoofSegment(\r\n currentPolygon,\r\n this.buildingInsights?.solarPotential.roofSegmentStats,\r\n this.rgbTiff.bounds,\r\n this.canvasElement,\r\n );\r\n\r\n if (bestMatch) {\r\n currentPolygon.details = {\r\n area,\r\n azimuth: bestMatch.azimuthDegrees,\r\n pitch: bestMatch.pitchDegrees,\r\n };\r\n } else {\r\n currentPolygon.details = {\r\n area,\r\n azimuth: 0,\r\n pitch: 0,\r\n };\r\n }\r\n\r\n this.scrollToCanvas();\r\n }\r\n\r\n this.drawPolygons();\r\n this.currentTool = moveTool;\r\n }\r\n\r\n private calculateSolarPanels({ redraw = true }: { redraw?: boolean } = {}) {\r\n const currentPolygon = this.getCurrentPolygon();\r\n\r\n if (!currentPolygon.details) {\r\n return;\r\n }\r\n\r\n if (this.roofPolygonsSolarPanels[currentPolygon._id]) {\r\n delete this.roofPolygonsSolarPanels[currentPolygon._id];\r\n }\r\n\r\n const convertedSolarPanel: SolarPanelType = {\r\n ...this.solarPanel,\r\n widthMeters: this.solarPanel.widthMeters / this.pixelInMeters,\r\n heightMeters: this.solarPanel.heightMeters / this.pixelInMeters,\r\n };\r\n const inset = BORDER_INSET / this.pixelInMeters;\r\n const solarPanels = getOptimalSolarPositionFully(\r\n currentPolygon,\r\n Object.values(this.obstructionPolygons),\r\n convertedSolarPanel,\r\n currentPolygon.details?.azimuth,\r\n inset,\r\n currentPolygon.details?.pitch,\r\n );\r\n this.roofPolygonsSolarPanels = {\r\n ...this.roofPolygonsSolarPanels,\r\n [currentPolygon._id]: {\r\n positionedPanels: solarPanels,\r\n sunniness: currentPolygon.details?.assignedRoofStats?.stats\r\n .sunshineQuantiles[5] ??\r\n this.buildingInsights.solarPotential.buildingStats\r\n .sunshineQuantiles[5] ??\r\n DEFAULT_SUNNINESS,\r\n },\r\n };\r\n if (redraw) {\r\n this.drawPolygons();\r\n }\r\n }\r\n\r\n private handlePitchChange(event: Event) {\r\n const target = event.target as HTMLInputElement;\r\n const pitch = parseFloat(target.value);\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (currentPolygon) {\r\n this.roofPolygons[currentPolygon._id].details.pitch = pitch;\r\n }\r\n if (\r\n currentPolygon.type === \"roof\" &&\r\n this.roofPolygonsSolarPanels[currentPolygon._id]\r\n ) {\r\n this.calculateSolarPanels();\r\n return;\r\n }\r\n }\r\n\r\n private handleAzimuthChange(event: Event) {\r\n const target = event.target as HTMLInputElement;\r\n const azimuth = parseFloat(target.value);\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (currentPolygon) {\r\n this.roofPolygons[currentPolygon._id].details.azimuth = azimuth;\r\n }\r\n if (\r\n currentPolygon.type === \"roof\" &&\r\n this.roofPolygonsSolarPanels[currentPolygon._id]\r\n ) {\r\n this.calculateSolarPanels();\r\n return;\r\n }\r\n }\r\n\r\n private handleToolSelect(tool: Tool) {\r\n const currentPolygon = this.getCurrentPolygon();\r\n if (\r\n currentPolygon && !currentPolygon.closed &&\r\n currentPolygon.points.length > 0\r\n ) {\r\n alert(\"Please close the polygon before selecting a tool\");\r\n // TODO translate\r\n return;\r\n }\r\n this.currentTool = tool;\r\n }\r\n\r\n private scrollToCanvas() {\r\n const canvasElement = this.el.querySelector(\"#map-draw-canvas\");\r\n if (canvasElement) {\r\n canvasElement.scrollIntoView({ behavior: \"smooth\" });\r\n }\r\n }\r\n\r\n private handleSettingsClick = () => {\r\n this.showSettings = true;\r\n };\r\n\r\n private handleSettingsClose = () => {\r\n this.showSettings = false;\r\n };\r\n\r\n private handleSettingsSave = (event: CustomEvent<Settings>) => {\r\n state.settings = event.detail;\r\n state.settingsVersion++;\r\n };\r\n\r\n render() {\r\n const t = getLanguageStrings(state.settings.language);\r\n const currentPolygon = this.getCurrentPolygon();\r\n return (\r\n <div\r\n class=\"flex flex-col justify-center items-center w-full h-full gap-4 bg-primary\"\r\n id=\"map-draw\"\r\n >\r\n {this.showInstructions && !state.isMobile && (\r\n <div class=\"w-full rounded-4xl p-4 bg-muted text-muted-foreground\">\r\n {t.mapDraw.instructions.parts.roof}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() => this.handleToolSelect(roofTool)}\r\n >\r\n <icon-selector name=\"house\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.obstruction}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() =>\r\n this.handleToolSelect(obstructionTool)}\r\n >\r\n <icon-selector name=\"octagon-minus\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.delete}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() => this.handleToolSelect(deleteTool)}\r\n >\r\n <icon-selector name=\"eraser\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.move}{\" \"}\r\n <button\r\n class=\"inline-flex items-center justify-center p-1 rounded-full hover:bg-surface-hover transition-colors\"\r\n onClick={() => this.handleToolSelect(moveTool)}\r\n >\r\n <icon-selector name=\"move\" inline={true} />\r\n </button>{\" \"}\r\n {t.mapDraw.instructions.parts.end}\r\n </div>\r\n )}\r\n <div class=\"w-full flex flex-row justify-between items-center\">\r\n {!state.isMobile && (this.showInstructions\r\n ? (\r\n <button\r\n class=\"px-4 py-2 rounded-4xl hover:bg-surface-hover transition-colors duration-200 bg-muted p-4 text-muted-foreground\"\r\n onClick={() => this.showInstructions = false}\r\n >\r\n {t.mapDraw.instructions.hide}\r\n </button>\r\n )\r\n : (\r\n <button\r\n class=\"px-4 py-2 rounded-4xl hover:bg-surface-hover transition-colors duration-200 bg-muted p-4 text-muted-foreground\"\r\n onClick={() => this.showInstructions = true}\r\n >\r\n {t.mapDraw.instructions.show}\r\n </button>\r\n ))}\r\n <button\r\n class=\"flex items-center gap-2 bg-muted p-2 rounded-4xl hover:bg-surface-hover text-muted-foreground\"\r\n onClick={this.handleSettingsClick}\r\n >\r\n <settings-icon />\r\n </button>\r\n </div>\r\n <div class=\"w-full\">\r\n {!state.isMobile && (\r\n <tool-box\r\n currentTool={this.currentTool}\r\n onToolSelect={(tool) => this.handleToolSelect(tool)}\r\n undoCallback={() => this.undo()}\r\n />\r\n )}\r\n </div>\r\n {this.loadingState === \"empty\" && (\r\n <div class=\"w-full\">\r\n <p class=\"text-muted text-center flex items-center justify-center rounded-4xl p-4 w-full bg-text-secondary\">\r\n {t.mapDraw.noAddressSelected}\r\n </p>\r\n </div>\r\n )}\r\n {(state.latitude && state.longitude &&\r\n this.loadingState === \"loading\") && (\r\n <div class=\"flex items-center justify-center w-full bg-opacity-75 z-20 pt-7 rounded-4xl\">\r\n <div class=\"animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-secondary\">\r\n </div>\r\n </div>\r\n )}\r\n <div class=\"flex items-start justify-center h-full w-full bg-primary rounded-4xl\">\r\n <div\r\n class=\"relative h-full flex items-center justify-center w-full rounded-4xl bg-secondary\"\r\n style={{\r\n aspectRatio: this.rgbTiff\r\n ? `${this.rgbTiff.width}/${this.rgbTiff.height}`\r\n : \"1/1\",\r\n }}\r\n >\r\n <canvas\r\n ref={(el) => this.canvasElement = el}\r\n class=\"absolute top-0 left-0 w-full h-full rounded-4xl\"\r\n id=\"map-draw-canvas\"\r\n style={{\r\n cursor: this.currentTool.cursor,\r\n }}\r\n >\r\n </canvas>\r\n <canvas\r\n ref={(el) => this.polygonCanvas = el}\r\n class=\"absolute top-0 left-0 w-full h-full rounded-4xl\"\r\n style={{\r\n cursor: this.currentTool.cursor,\r\n }}\r\n >\r\n </canvas>\r\n </div>\r\n </div>\r\n {currentPolygon?.closed && (\r\n <div class=\"w-full\">\r\n <polygon-buttons\r\n currentTool={this.currentTool.name}\r\n calculateSolarPanels={() =>\r\n this.calculateSolarPanels()}\r\n selectEdgeTool={() =>\r\n this.handleToolSelect(markRoofEdgeTool)}\r\n />\r\n </div>\r\n )}\r\n {!state.isMobile && (\r\n <div class=\"w-full\">\r\n <polygon-information\r\n currentPolygon={currentPolygon}\r\n positionedPanels={currentPolygon\r\n ? this\r\n .roofPolygonsSolarPanels[currentPolygon._id]\r\n ?.positionedPanels\r\n : undefined}\r\n handleAzimuthChange={(event) =>\r\n this.handleAzimuthChange(event)}\r\n handlePitchChange={(event) =>\r\n this.handlePitchChange(event)}\r\n calculateSolarPanels={() =>\r\n this.calculateSolarPanels()}\r\n />\r\n </div>\r\n )}\r\n <div class=\"w-full\">\r\n <solar-system-form\r\n systemConfigs={this.roofPolygonsSolarPanels}\r\n roofPolygons={this.roofPolygons}\r\n obstructionPolygons={this.obstructionPolygons}\r\n />\r\n </div>\r\n {this.showSettings && (\r\n <settings-modal\r\n settings={state.settings}\r\n onClose={this.handleSettingsClose}\r\n onSave={this.handleSettingsSave}\r\n />\r\n )}\r\n </div>\r\n );\r\n }\r\n}\r\n"],"version":3}
|