Skip to content

Commit

Permalink
Merge pull request #316 from open-pv/291-generalize-select-method
Browse files Browse the repository at this point in the history
Generalize select method #291
  • Loading branch information
FlorianK13 authored Oct 4, 2024
2 parents 0e6a874 + 247c2aa commit 8bcf30c
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 91 deletions.
8 changes: 5 additions & 3 deletions public/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"next": "Nächste",
"previous": "Vorherige",
"close": "Schließen",
"delete": "Löschen",
"searchField": {
"placeholder": "Geben Sie Ihre Adresse oder Koordinaten ein - z.B. Lange Point 20, Freising"
},
Expand Down Expand Up @@ -96,16 +97,17 @@
"leftMouse": "Linke Maustaste: Bewegung auf der Karte",
"rightMouse": "Rechte Maustaste: Rotation der Karte",
"wheel": "Mausrad: Vergrößern und Verkleinern",
"doubleClick": "Doppelklick: Weiteres Gebäude für Simulation auswählen",
"doubleClick": "Doppelklick: Auswählen von Gebäude oder PV-Anlage",
"touch": {
"leftMouse": "Ein Finger: Bewegung auf der Karte",
"rightMouse": "Zwei Finger: Rotation der Karte",
"wheel": "Zwei Finger: Vergrößern und Verkleinern",
"doubleClick": "Zweimal kurz auf Gebäude tippen: Weiteres Gebäude für Simulation auswählen"
"doubleClick": "Zweimal kurz tippen: Auswählen von Gebäude oder PV-Anlage"
}
},
"savingsCalculation": {
"button": "Wirtschaftlichkeit der Anlage berechnen",
"notificationLabel": "Für die ausgewählte PV-Anlage:",
"button": "Wirtschaftlichkeit berechnen",
"consumptionTitle": "Jährlicher Stromverbrauch in kWh",
"consumptionHelperInfo": "Als grober Schätzwert gilt: Rechne pro Person im Haushalt mit 800 kWh, für eine Wärmepumpe 2000 kWh und pro Elektroauto weitere 2000 kWh.",
"consumptionHelperLabel": "[So berechnen Sie ihren Stromverbrauch]",
Expand Down
6 changes: 4 additions & 2 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"next": "Next",
"previous": "Previous",
"close": "Close",
"delete": "Delete",
"searchField": {
"placeholder": "Enter your address or coordinates - e.g. Lange Point 20, Freising"
},
Expand Down Expand Up @@ -96,15 +97,16 @@
"leftMouse": "Left Mouse Button: Move on the map",
"rightMouse": "Right Mouse Button: Rotate the map",
"wheel": "Mouse Wheel: Zoom in and out",
"doubleClick": "Double click: Choose another building for a simulation",
"doubleClick": "Double click: Select a builing or PV system",
"touch": {
"leftMouse": "One finger: Move on the map",
"rightMouse": "Two fingers: Rotate the map",
"wheel": "Two fingers: Zoom in and out",
"doubleClick": "Double-tap on a building: Select another building for simulation"
"doubleClick": "Double-tap: Select a builing or PV system"
}
},
"savingsCalculation": {
"notificationLabel": "Continue with chosen pv system:",
"button": "Calculate Earnings",
"consumptionTitle": "Annual electricity consumption in kWh",
"consumptionHelperInfo": "As a rough estimate: Calculate 800 kWh per person in the household, 2000 kWh for a heat pump, and an additional 2000 kWh per electric car.",
Expand Down
32 changes: 26 additions & 6 deletions src/components/PVSimulation/SavingsCalculation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ import {
import React, { useState } from "react"
import { useTranslation } from "react-i18next"

function SavingCalculation({ pvSystems }) {
function SavingCalculation({
selectedPVSystem,
setSelectedPVSystem,
onCloseAlert,
}) {
const { isOpen, onOpen, onClose } = useDisclosure({ defaultIsOpen: false })
const { isOpen: isOpenResultFade, onToggle: onToggleResultFade } =
useDisclosure({ defaultIsOpen: false })
Expand All @@ -32,9 +36,12 @@ function SavingCalculation({ pvSystems }) {
const [selfConsumption, setSelfConsumption] = useState(0)
const [annualSavings, setAnnualSavings] = useState(0)
let pvProduction
if (pvSystems.length > 0) {
if (selectedPVSystem.length > 0) {
pvProduction = Math.round(
pvSystems.reduce((previous, current) => previous + current.annualYield, 0)
selectedPVSystem.reduce(
(previous, current) => previous + current.annualYield,
0
)
)
}

Expand Down Expand Up @@ -118,12 +125,25 @@ function SavingCalculation({ pvSystems }) {

return (
<>
{pvSystems.length > 0 && (
<Button onClick={onOpen} className="button-high-prio">
{selectedPVSystem.length > 0 && (
<Button
colorScheme="teal"
onClick={() => {
onOpen()
}}
>
{t("savingsCalculation.button")}
</Button>
)}
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<Modal
isOpen={isOpen}
onClose={() => {
onClose()
onCloseAlert()
setSelectedPVSystem([])
}}
size="xl"
>
<ModalOverlay />
<ModalContent>
<ModalHeader>{t("savingsCalculation.button")}</ModalHeader>
Expand Down
93 changes: 51 additions & 42 deletions src/components/ThreeViewer/Controls/CustomMapControl.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,58 @@ function CustomMapControl(props) {
const handleInteraction = (event) => {
event.preventDefault()

const isTouch = event.type.startsWith("touch")
const clientX = isTouch ? event.touches[0].clientX : event.clientX
const clientY = isTouch ? event.touches[0].clientY : event.clientY

const rect = event.target.getBoundingClientRect()
mouse.current.x = ((clientX - rect.left) / rect.width) * 2 - 1
mouse.current.y = (-(clientY - rect.top) / rect.height) * 2 + 1

raycaster.current.setFromCamera(mouse.current, camera)
const intersects = raycaster.current.intersectObjects(scene.children, true)

if (intersects.length > 0) {
const intersectedMesh = intersects[0].object
console.log("Intersected Mesh", intersectedMesh)

if (!intersectedMesh) return

if (
intersectedMesh.geometry.name &&
(intersectedMesh.geometry.name.includes("surrounding") ||
intersectedMesh.geometry.name.includes("background"))
) {
const existingIndex = props.selectedMesh.findIndex(
(mesh) => mesh.geometry.name === intersectedMesh.geometry.name
)

if (existingIndex > -1) {
props.setSelectedMesh([
...props.selectedMesh.slice(0, existingIndex),
...props.selectedMesh.slice(existingIndex + 1),
])
} else {
props.setSelectedMesh([
...props.selectedMesh,
{
geometry: intersectedMesh.geometry,
material: intersectedMesh.material,
},
])
}
}
} else {
/**
* Returns the list of intersected objects. An intersected object is an object
* that lies directly below the mouse cursor.
*/
const getIntersects = () => {
const isTouch = window.isTouchDevice
const clientX = isTouch ? event.touches[0].clientX : event.clientX
const clientY = isTouch ? event.touches[0].clientY : event.clientY

const rect = event.target.getBoundingClientRect()
mouse.current.x = ((clientX - rect.left) / rect.width) * 2 - 1
mouse.current.y = (-(clientY - rect.top) / rect.height) * 2 + 1

raycaster.current.setFromCamera(mouse.current, camera)

return raycaster.current.intersectObjects(scene.children, true)
}
const intersects = getIntersects()

if (intersects.length === 0) {
console.log("No children in the intersected mesh.")
return
}

// Filter out Sprites (ie the labels of PV systems)
let i = 0
while (i < intersects.length && intersects[i].object.type === "Sprite") {
i++
}
if (i === intersects.length) {
console.log("Only Sprite objects found in intersections.")
return
}

let intersectedMesh = intersects[i].object
console.log("Intersected Mesh", intersectedMesh)

if (!intersectedMesh) return
if (!intersectedMesh.geometry.name) {
console.log(
"There is a mesh, but it has no name so I don't know what to do."
)
return
}
if (
intersectedMesh.geometry.name.includes("surrounding") ||
intersectedMesh.geometry.name.includes("background")
) {
props.setSelectedMesh([intersectedMesh])
}
if (intersectedMesh.geometry.name.includes("pvSystem")) {
props.setSelectedPVSystem([intersectedMesh.geometry])
}
}

Expand Down
21 changes: 21 additions & 0 deletions src/components/ThreeViewer/Meshes/HighlitedPVSystem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react"
import * as THREE from "three"

export function HighlightedPVSystem({ geometries }) {
return (
<>
{geometries.map((geometry, index) => (
<mesh
key={index}
geometry={geometry}
material={
new THREE.MeshLambertMaterial({
color: "red",
transparent: false,
})
}
/>
))}
</>
)
}
27 changes: 11 additions & 16 deletions src/components/ThreeViewer/Meshes/PVSystems.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,16 @@ import TextSprite from "../TextSprite"
export const PVSystems = ({ pvSystems }) => {
return (
<>
{pvSystems.map((system, index) => (
<PVSystem
key={index}
geometry={system.geometry}
annualYield={system.annualYield}
area={system.area}
/>
{pvSystems.map((geometry) => (
<PVSystem geometry={geometry} />
))}
</>
)
}

export function createPVSystem({
setPVSystems,
setSelectedPVSystem,
pvPoints,
setPVPoints,
simulationMeshes,
Expand Down Expand Up @@ -58,6 +54,7 @@ export function createPVSystem({
"position",
new THREE.Float32BufferAttribute(bufferTriangles, 3)
)
geometry.name = "pvSystem"

let subdividedTriangles = []
const triangleSubdivisionThreshold = 0.8
Expand Down Expand Up @@ -124,17 +121,15 @@ export function createPVSystem({
)
const annualYield = polygonArea * polygonIntensity

const newPVSystem = {
geometry: geometry,
annualYield: annualYield,
area: polygonArea,
}
geometry.annualYield = annualYield
geometry.area = polygonArea

setPVSystems((prevSystems) => [...prevSystems, newPVSystem])
setPVSystems((prevSystems) => [...prevSystems, geometry])
setPVPoints([])
setSelectedPVSystem([geometry])
}

const PVSystem = ({ geometry, annualYield, area }) => {
const PVSystem = ({ geometry }) => {
const textRef = useRef()

const center = calculateCenter(geometry.attributes.position.array)
Expand All @@ -161,9 +156,9 @@ const PVSystem = ({ geometry, annualYield, area }) => {
/>

<TextSprite
text={`Jahresertrag: ${Math.round(annualYield).toLocaleString(
text={`Jahresertrag: ${Math.round(geometry.annualYield).toLocaleString(
"de"
)} kWh pro Jahr\nFläche: ${area.toPrecision(3)}m²`}
)} kWh pro Jahr\nFläche: ${geometry.area.toPrecision(3)}m²`}
position={center}
/>
</>
Expand Down
40 changes: 20 additions & 20 deletions src/components/ThreeViewer/Overlay.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ import {
} from "@chakra-ui/react"
import React from "react"
import { useTranslation } from "react-i18next"
import { simulationForNewBuilding } from "../../simulation/main"
import SavingCalculation from "../PVSimulation/SavingsCalculation"

import ButtonWithHoverHelp from "../Template/ButtonWithHoverHelp"
import SliderWithLabel from "../Template/SliderWithLabel"
import { createPVSystem } from "./Meshes/PVSystems"
import SelectionNotificationBuilding from "./SelectionNotificationBuilding"
import SelectionNotificationPV from "./SelectionNotificationPV"

function Overlay({
frontendState,
Expand All @@ -36,6 +37,8 @@ function Overlay({
setShowTerrain,
selectedMesh,
setSelectedMesh,
selectedPVSystem,
setSelectedPVSystem,
geometries,
geoLocation,
pvSystems,
Expand All @@ -60,6 +63,7 @@ function Overlay({
const handleCreatePVButtonClick = () => {
createPVSystem({
setPVSystems,
setSelectedPVSystem,
pvPoints,
setPVPoints,
simulationMeshes,
Expand All @@ -74,6 +78,19 @@ function Overlay({
return (
<>
<OverlayWrapper>
<SelectionNotificationPV
selectedPVSystem={selectedPVSystem}
setSelectedPVSystem={setSelectedPVSystem}
setPVSystems={setPVSystems}
/>
<SelectionNotificationBuilding
selectedMesh={selectedMesh}
setSelectedMesh={setSelectedMesh}
simulationMeshes={simulationMeshes}
setSimulationMeshes={setSimulationMeshes}
geometries={geometries}
geoLocation={geoLocation}
/>
{frontendState == "Results" && (
<>
<Button
Expand Down Expand Up @@ -118,24 +135,7 @@ function Overlay({
hoverText={t("button.drawPVSystemHover")}
/>
)}
<SavingCalculation pvSystems={pvSystems} />
{selectedMesh.length > 0 && (
<Button
className="button-high-prio"
onClick={async () =>
await simulationForNewBuilding({
selectedMesh,
setSelectedMesh,
simulationMeshes,
setSimulationMeshes,
geometries,
geoLocation,
})
}
>
{t("button.simulateBuilding")}
</Button>
)}

{frontendState == "DrawPV" && (
<>
{pvPoints.length > 0 && (
Expand Down
Loading

0 comments on commit 8bcf30c

Please sign in to comment.