From 7669a9473f9da454ccf991719d58b67eb7d675b5 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 14:29:39 +0200
Subject: [PATCH 01/10] Refactor pvSystems #242
The react state pvSystems should contain relevant
metadata, not only indices.
---
src/components/ThreeViewer/Meshes/PVSystem.js | 53 ----
.../ThreeViewer/Meshes/PVSystems.js | 297 ++++++++++--------
src/components/ThreeViewer/Overlay.js | 170 ++++++----
src/components/ThreeViewer/OverlayDrawPV.js | 13 +-
src/components/ThreeViewer/Scene.js | 11 +-
src/pages/Simulation.js | 9 +-
6 files changed, 296 insertions(+), 257 deletions(-)
delete mode 100644 src/components/ThreeViewer/Meshes/PVSystem.js
diff --git a/src/components/ThreeViewer/Meshes/PVSystem.js b/src/components/ThreeViewer/Meshes/PVSystem.js
deleted file mode 100644
index 09414721..00000000
--- a/src/components/ThreeViewer/Meshes/PVSystem.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import { useFrame } from "@react-three/fiber"
-import React, { useRef } from "react"
-import * as THREE from "three"
-import TextSprite from "../TextSprite"
-
-const PVSystem = ({ geometry, annualYield, area }) => {
- const textRef = useRef()
-
- const center = calculateCenter(geometry.attributes.position.array)
-
- useFrame(({ camera }) => {
- if (textRef.current) {
- textRef.current.quaternion.copy(camera.quaternion)
- }
- })
-
- return (
- <>
-
-
-
- >
- )
-}
-
-const calculateCenter = (points) => {
- const length = points.length / 3
- const sum = points.reduce(
- (acc, value, index) => {
- acc[index % 3] += value
- return acc
- },
- [0, 0, 0]
- )
- return new THREE.Vector3(sum[0] / length, sum[1] / length, sum[2] / length)
-}
-
-export default PVSystem
diff --git a/src/components/ThreeViewer/Meshes/PVSystems.js b/src/components/ThreeViewer/Meshes/PVSystems.js
index a3aba617..85f28508 100644
--- a/src/components/ThreeViewer/Meshes/PVSystems.js
+++ b/src/components/ThreeViewer/Meshes/PVSystems.js
@@ -1,159 +1,202 @@
-import { useThree } from "@react-three/fiber"
-import React, { useEffect, useState } from "react"
+import React, { useRef } from "react"
+import { useFrame } from "react-three-fiber"
import * as THREE from "three"
import * as BufferGeometryUtils from "three/addons/utils/BufferGeometryUtils.js"
-import PVSystem from "./PVSystem"
+import TextSprite from "../TextSprite"
-const PVSystems = ({
- visiblePVSystems,
+export const PVSystems = ({ pvSystems }) => {
+ console.log("PVSystems in three module", pvSystems)
+ return (
+ <>
+ {pvSystems.map((system, index) => (
+
+ ))}
+ >
+ )
+}
+
+export function createPVSystem({
+ setPVSystems,
pvPoints,
setPVPoints,
simulationMeshes,
-}) => {
- const points = pvPoints.map((obj) => obj.point) // pvPoints is a list of objects, each object has a point and a normal
-
- const { scene } = useThree()
- const [pvSystems, setPVSystems] = useState([])
+}) {
+ const points = pvPoints.map((obj) => obj.point)
+ if (pvPoints.length < 3) {
+ console.log("Not enough points to create a polygon")
+ return
+ }
+ const geometry = new THREE.BufferGeometry()
+ const vertices = []
+ points.forEach((point) => {
+ vertices.push(point.x, point.y, point.z)
+ })
- useEffect(() => {
- if (visiblePVSystems.length === 0 || pvPoints.length < 3) {
- console.log("Not enough points to create a polygon")
- return
- }
- const geometry = new THREE.BufferGeometry()
- const vertices = []
- points.forEach((point) => {
- vertices.push(point.x, point.y, point.z)
- })
+ const triangles = []
+ const bufferTriangles = []
+ const normalOffset = 0.1 // Adjust this value as needed
- const triangles = []
- const bufferTriangles = []
- const normalOffset = 0.1 // Adjust this value as needed
+ for (let i = 1; i < pvPoints.length - 1; i++) {
+ const v0 = pvPoints[0]
+ const v1 = pvPoints[i]
+ const v2 = pvPoints[i + 1]
- for (let i = 1; i < pvPoints.length - 1; i++) {
- const v0 = pvPoints[0]
- const v1 = pvPoints[i]
- const v2 = pvPoints[i + 1]
+ const shift = (element) => ({
+ x: element.point.x + element.normal.x * normalOffset,
+ y: element.point.y + element.normal.y * normalOffset,
+ z: element.point.z + element.normal.z * normalOffset,
+ })
- const shift = (element) => ({
- x: element.point.x + element.normal.x * normalOffset,
- y: element.point.y + element.normal.y * normalOffset,
- z: element.point.z + element.normal.z * normalOffset,
- })
+ const sv0 = shift(v0)
+ const sv1 = shift(v1)
+ const sv2 = shift(v2)
+
+ triangles.push({ a: v0.point, b: v1.point, c: v2.point })
+ bufferTriangles.push(
+ sv0.x,
+ sv0.y,
+ sv0.z,
+ sv1.x,
+ sv1.y,
+ sv1.z,
+ sv2.x,
+ sv2.y,
+ sv2.z
+ )
+ }
- const sv0 = shift(v0)
- const sv1 = shift(v1)
- const sv2 = shift(v2)
-
- triangles.push({ a: v0.point, b: v1.point, c: v2.point })
- bufferTriangles.push(
- sv0.x,
- sv0.y,
- sv0.z,
- sv1.x,
- sv1.y,
- sv1.z,
- sv2.x,
- sv2.y,
- sv2.z
- )
- }
+ geometry.setAttribute(
+ "position",
+ new THREE.Float32BufferAttribute(bufferTriangles, 3)
+ )
- geometry.setAttribute(
- "position",
- new THREE.Float32BufferAttribute(bufferTriangles, 3)
+ let subdividedTriangles = []
+ const triangleSubdivisionThreshold = 0.8
+ triangles.forEach((triangle) => {
+ subdividedTriangles = subdividedTriangles.concat(
+ subdivideTriangle(triangle, triangleSubdivisionThreshold)
)
+ })
- let subdividedTriangles = []
- const triangleSubdivisionThreshold = 0.8
- triangles.forEach((triangle) => {
- subdividedTriangles = subdividedTriangles.concat(
- subdivideTriangle(triangle, triangleSubdivisionThreshold)
- )
- })
-
- const geometries = []
+ const geometries = []
- simulationMeshes.forEach((mesh) => {
- const geom = mesh.geometry.clone()
- geom.applyMatrix4(mesh.matrixWorld)
- geometries.push(geom)
- })
- const simulationGeometry = BufferGeometryUtils.mergeGeometries(
- geometries,
- true
+ simulationMeshes.forEach((mesh) => {
+ const geom = mesh.geometry.clone()
+ geom.applyMatrix4(mesh.matrixWorld)
+ geometries.push(geom)
+ })
+ const simulationGeometry = BufferGeometryUtils.mergeGeometries(
+ geometries,
+ true
+ )
+ const polygonPrefilteringCutoff = 10
+ const prefilteredPolygons = filterPolygonsByDistance(
+ simulationGeometry,
+ points,
+ polygonPrefilteringCutoff
+ )
+ const newVertices = []
+ const newColors = []
+ const newIntensities = []
+ subdividedTriangles.forEach((triangle) => {
+ newVertices.push(triangle.a.x, triangle.a.y, triangle.a.z)
+ newVertices.push(triangle.b.x, triangle.b.y, triangle.b.z)
+ newVertices.push(triangle.c.x, triangle.c.y, triangle.c.z)
+ })
+ for (let i = 0; i < newVertices.length; i += 3) {
+ const vertex = new THREE.Vector3(
+ newVertices[i],
+ newVertices[i + 1],
+ newVertices[i + 2]
)
- const polygonPrefilteringCutoff = 10
- const prefilteredPolygons = filterPolygonsByDistance(
- simulationGeometry,
- points,
+ const closestPolygon = findClosestPolygon(
+ vertex,
+ prefilteredPolygons,
polygonPrefilteringCutoff
)
- const newVertices = []
- const newColors = []
- const newIntensities = []
- subdividedTriangles.forEach((triangle) => {
- newVertices.push(triangle.a.x, triangle.a.y, triangle.a.z)
- newVertices.push(triangle.b.x, triangle.b.y, triangle.b.z)
- newVertices.push(triangle.c.x, triangle.c.y, triangle.c.z)
- })
- for (let i = 0; i < newVertices.length; i += 3) {
- const vertex = new THREE.Vector3(
- newVertices[i],
- newVertices[i + 1],
- newVertices[i + 2]
- )
- const closestPolygon = findClosestPolygon(
- vertex,
- prefilteredPolygons,
- polygonPrefilteringCutoff
+ if (closestPolygon) {
+ const projectedVertex = projectOntoTriangle(vertex, closestPolygon)
+ const color = getColorAtPointOnTriangle(projectedVertex, closestPolygon)
+ const intensity = getIntensityAtPointOnTriangle(
+ projectedVertex,
+ closestPolygon
)
- if (closestPolygon) {
- const projectedVertex = projectOntoTriangle(vertex, closestPolygon)
- const color = getColorAtPointOnTriangle(projectedVertex, closestPolygon)
- const intensity = getIntensityAtPointOnTriangle(
- projectedVertex,
- closestPolygon
- )
- newColors.push(color.r, color.g, color.b)
- newIntensities.push(intensity)
- } else {
- newColors.push(1, 1, 1)
- newIntensities.push(-1)
- }
+ newColors.push(color.r, color.g, color.b)
+ newIntensities.push(intensity)
+ } else {
+ newColors.push(1, 1, 1)
+ newIntensities.push(-1)
}
- const polygonArea = calculatePolygonArea(triangles)
- const polygonIntensity = calculatePolygonIntensity(
- newVertices,
- newIntensities
- )
- const annualYield = polygonArea * polygonIntensity
+ }
+ const polygonArea = calculatePolygonArea(triangles)
+ const polygonIntensity = calculatePolygonIntensity(
+ newVertices,
+ newIntensities
+ )
+ const annualYield = polygonArea * polygonIntensity
- const newPVSystem = {
- geometry: geometry,
- annualYield: annualYield,
- area: polygonArea,
- }
+ const newPVSystem = {
+ geometry: geometry,
+ annualYield: annualYield,
+ area: polygonArea,
+ }
+ console.log("newPVSystem", newPVSystem)
+
+ setPVSystems((prevSystems) => [...prevSystems, newPVSystem])
+ setPVPoints([])
+}
+
+const PVSystem = ({ geometry, annualYield, area }) => {
+ const textRef = useRef()
- setPVSystems((prevSystems) => [...prevSystems, newPVSystem])
- setPVPoints([])
- }, [visiblePVSystems])
+ const center = calculateCenter(geometry.attributes.position.array)
+
+ useFrame(({ camera }) => {
+ if (textRef.current) {
+ textRef.current.quaternion.copy(camera.quaternion)
+ }
+ })
return (
<>
- {pvSystems.map((system, index) => (
-
- ))}
+
+
+
>
)
}
-export default PVSystems
+const calculateCenter = (points) => {
+ const length = points.length / 3
+ const sum = points.reduce(
+ (acc, value, index) => {
+ acc[index % 3] += value
+ return acc
+ },
+ [0, 0, 0]
+ )
+ return new THREE.Vector3(sum[0] / length, sum[1] / length, sum[2] / length)
+}
function subdivideTriangle(triangle, threshold) {
const distance = (p1, p2) =>
diff --git a/src/components/ThreeViewer/Overlay.js b/src/components/ThreeViewer/Overlay.js
index f53889cc..dc58db82 100644
--- a/src/components/ThreeViewer/Overlay.js
+++ b/src/components/ThreeViewer/Overlay.js
@@ -21,13 +21,13 @@ import {
UnorderedList,
useDisclosure,
} 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 HoverHelp from "../Template/HoverHelp"
import SliderWithLabel from "../Template/SliderWithLabel"
-
-import React from "react"
-import ButtonWithHoverHelp from "../Template/ButtonWithHoverHelp"
import OverlayDrawPV from "./OverlayDrawPV"
function Overlay({
@@ -39,8 +39,8 @@ function Overlay({
setSelectedMesh,
geometries,
geoLocation,
- visiblePVSystems,
- setvisiblePVSystems,
+ pvSystems,
+ setPVSystems,
pvPoints,
setPVPoints,
simulationMeshes,
@@ -60,72 +60,81 @@ function Overlay({
const btnRef = React.useRef()
return (
-
- {frontendState == "Results" && (
- <>
+ <>
+
+ {frontendState == "Results" && (
+ <>
+
+ {
+ setFrontendState("DrawPV")
+ onCloseDrawer()
+ }}
+ hoverText={
+ "PV-Anlage in der Karte einzeichnen und Jahresbetrag berechnen."
+ }
+ />
+ >
+ )}
+ {frontendState == "DrawPV" && (
+
+ )}
+ {selectedMesh.length > 0 && (
- {
- setFrontendState("DrawPV")
- onCloseDrawer()
- }}
- hoverText={
- "PV-Anlage in der Karte einzeichnen und Jahresbetrag berechnen."
- }
- />
- >
- )}
- {frontendState == "DrawPV" && (
-
- )}
- {selectedMesh.length > 0 && (
+ )}
- )}
-
-
-
-
+
+
+
+
+
+
+ >
)
}
@@ -167,6 +176,45 @@ const OverlayWrapper = ({ children }) => {
)
}
+const HighPrioWrapper = ({ children }) => {
+ return (
+ <>
+ *": {
+ pointerEvents: "auto",
+ },
+ }}
+ >
+
+ {children}
+
+
+ >
+ )
+}
+
const CustomDrawer = ({ isOpen, onClose, showTerrain, setShowTerrain }) => {
const { t } = useTranslation()
const [sliderValue, setSliderValue] = React.useState(window.numSimulations)
diff --git a/src/components/ThreeViewer/OverlayDrawPV.js b/src/components/ThreeViewer/OverlayDrawPV.js
index 3eb02be0..b01ff422 100644
--- a/src/components/ThreeViewer/OverlayDrawPV.js
+++ b/src/components/ThreeViewer/OverlayDrawPV.js
@@ -1,18 +1,23 @@
import { Button } from "@chakra-ui/react"
import React from "react"
import { useTranslation } from "react-i18next"
+import { createPVSystem } from "./Meshes/PVSystems"
export default function OverlayDrawPV({
- visiblePVSystems,
- setvisiblePVSystems,
+ setPVSystems,
pvPoints,
setPVPoints,
setFrontendState,
+ simulationMeshes,
}) {
const { t } = useTranslation()
const handleCreatePVButtonClick = () => {
- const nextIndex = visiblePVSystems.length
- setvisiblePVSystems([...visiblePVSystems, nextIndex])
+ createPVSystem({
+ setPVSystems,
+ pvPoints,
+ setPVPoints,
+ simulationMeshes,
+ })
setFrontendState("Results")
}
diff --git a/src/components/ThreeViewer/Scene.js b/src/components/ThreeViewer/Scene.js
index acdaac7e..e9fc9779 100644
--- a/src/components/ThreeViewer/Scene.js
+++ b/src/components/ThreeViewer/Scene.js
@@ -4,7 +4,7 @@ import { Canvas } from "react-three-fiber"
import CustomMapControl from "./Controls/CustomMapControl"
import DrawPVControl from "./Controls/DrawPVControl"
import { HighlightedMesh } from "./Meshes/HiglightedMesh"
-import PVSystems from "./Meshes/PVSystems"
+import { PVSystems } from "./Meshes/PVSystems"
import SimulationMesh from "./Meshes/SimulationMesh"
import SurroundingMesh from "./Meshes/SurroundingMesh"
import Points from "./Points"
@@ -15,7 +15,7 @@ const Scene = ({
simulationMeshes,
showTerrain,
frontendState,
- visiblePVSystems,
+ pvSystems,
selectedMesh,
setSelectedMesh,
pvPoints,
@@ -68,12 +68,7 @@ const Scene = ({
)}
{frontendState == "DrawPV" && }
-
+ {pvSystems.length > 0 && }
{simulationMeshes.length > 0 && }
diff --git a/src/pages/Simulation.js b/src/pages/Simulation.js
index d6ff12f7..fcbff248 100644
--- a/src/pages/Simulation.js
+++ b/src/pages/Simulation.js
@@ -19,7 +19,7 @@ function Index() {
// simulationProgress is used for the loading bar
const [simulationProgress, setSimulationProgress] = useState(0)
// A list of visible PV Systems - they get visible after they are drawn on a building and calculated
- const [visiblePVSystems, setvisiblePVSystems] = useState([])
+ const [pvSystems, setPVSystems] = useState([])
// pvPoints are the red points that appear when drawing PV systems
const [pvPoints, setPVPoints] = useState([])
@@ -70,8 +70,8 @@ function Index() {
setSelectedMesh={setSelectedMesh}
geometries={geometries}
geoLocation={location}
- setvisiblePVSystems={setvisiblePVSystems}
- visiblePVSystems={visiblePVSystems}
+ setPVSystems={setPVSystems}
+ pvSystems={pvSystems}
pvPoints={pvPoints}
setPVPoints={setPVPoints}
simulationMeshes={simulationMeshes}
@@ -86,7 +86,8 @@ function Index() {
simulationMeshes={simulationMeshes}
showTerrain={showTerrain}
frontendState={frontendState}
- visiblePVSystems={visiblePVSystems}
+ pvSystems={pvSystems}
+ setPVSystems={setPVSystems}
selectedMesh={selectedMesh}
setSelectedMesh={setSelectedMesh}
pvPoints={pvPoints}
From 7eb36a2f68b47027074e21947e3f0b29aa8a8270 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 14:29:56 +0200
Subject: [PATCH 02/10] Add calculation of savings #242
---
.../PVSimulation/SavingsCalculation.js | 210 +++++++++++++-----
1 file changed, 155 insertions(+), 55 deletions(-)
diff --git a/src/components/PVSimulation/SavingsCalculation.js b/src/components/PVSimulation/SavingsCalculation.js
index 959ae626..c3c17102 100644
--- a/src/components/PVSimulation/SavingsCalculation.js
+++ b/src/components/PVSimulation/SavingsCalculation.js
@@ -1,13 +1,9 @@
import {
- Box,
Button,
- Checkbox,
- CheckboxGroup,
- Circle,
- Flex,
FormControl,
FormLabel,
Input,
+ ListItem,
Modal,
ModalBody,
ModalCloseButton,
@@ -15,66 +11,170 @@ import {
ModalFooter,
ModalHeader,
ModalOverlay,
- Radio,
- RadioGroup,
- Stack,
+ UnorderedList,
useDisclosure,
} from "@chakra-ui/react"
-
import React, { useState } from "react"
import { useTranslation } from "react-i18next"
+import HoverHelp from "../Template/HoverHelp"
+
+function SavingCalculation({ PVSystems }) {
+ const { isOpen, onOpen, onClose } = useDisclosure({ defaultIsOpen: false })
+ const { t } = useTranslation()
+ const [annualConsumption, setAnnualConsumption] = useState("")
+ const [storageCapacity, setStorageCapacity] = useState("")
+ const [electricityPrice, setElectricityPrice] = useState(0.25)
+ const [selfConsumption, setSelfConsumption] = useState(0)
+ const [annualSavings, setAnnualSavings] = useState(0)
+
+ async function handleCalculateSaving() {
+ async function calculateSaving({
+ consumptionHousehold,
+ storageCapacity,
+ electricityPrice,
+ setSelfConsumption,
+ setAnnualSavings,
+ }) {
+ const pvProduction = 6000
+ const response = await fetch(
+ "https://www.openpv.de/data/savings_calculation/cons_prod.json"
+ )
+ const data = await response.json()
+
+ const normalizedConsumption = data["Consumption"]
+ const normalizedProduction = data["Production"]
+
+ const result = {}
+ let currentStorageLevel = 0
+ for (const timestamp in normalizedConsumption) {
+ const consumptionValue =
+ (normalizedConsumption[timestamp] * consumptionHousehold) / 1000
+ const productionValue =
+ (normalizedProduction[timestamp] * pvProduction) / 1000
+
+ let selfConsumption = 0
+ let excessProduction = 0
+
+ if (productionValue > consumptionValue) {
+ selfConsumption = consumptionValue
+ excessProduction = productionValue - consumptionValue
+
+ // Charge the storage
+ const availableStorageSpace = storageCapacity - currentStorageLevel
+ const chargedAmount = Math.min(
+ excessProduction,
+ availableStorageSpace
+ )
+ currentStorageLevel += chargedAmount
+ } else {
+ const productionDeficit = consumptionValue - productionValue
-function SavingCalculation() {
- const { isOpen, onOpen, onClose } = useDisclosure({ defaultIsOpen: true })
- const [currentPage, setCurrentPage] = useState(1)
- const { t, i18n } = useTranslation()
+ // Use storage if available
+ const usedFromStorage = Math.min(
+ productionDeficit,
+ currentStorageLevel
+ )
+ currentStorageLevel -= usedFromStorage
- const calculateSaving = () => {
- console.log("Savings")
+ selfConsumption = productionValue + usedFromStorage
+ }
+
+ result[timestamp] = selfConsumption
+ }
+
+ let selfConsumedElectricity = Object.values(result).reduce(
+ (acc, val) => acc + val,
+ 0
+ )
+
+ console.log(
+ selfConsumedElectricity,
+ "kWh are self consumed in the household"
+ )
+
+ setSelfConsumption(Math.round(selfConsumedElectricity))
+ setAnnualSavings(Math.round(selfConsumedElectricity * electricityPrice))
+ }
+
+ await calculateSaving({
+ consumptionHousehold: parseFloat(annualConsumption),
+ storageCapacity: storageCapacity,
+ electricityPrice: electricityPrice,
+ setSelfConsumption: setSelfConsumption,
+ setAnnualSavings: setAnnualSavings,
+ })
}
+
const initialRef = React.useRef(null)
- const finalRef = React.useRef(null)
- const [value, setValue] = React.useState("1")
+ console.log("PVSystems", PVSystems)
return (
-
-
-
- {"Wirtschaftlichkeit berechnen"}
-
-
- <>
-
- Jährlicher Stromverbrauch
-
-
-
- Wann verbrauche ich meinen Strom?
-
-
- Morgens und Abends
- Morgens, Mittags und Abends
-
-
-
- Ich besitze oder plane den Kauf
-
- einer Wärmepumpe
- eines Elektroautos
-
- >
-
-
-
-
-
-
-
+ <>
+ {PVSystems.length > 0 && (
+
+ )}
+
+
+
+ {"Wirtschaftlichkeit berechnen"}
+
+
+ <>
+
+
+ Jährlicher Stromverbrauch{" "}
+
+
+ setAnnualConsumption(e.target.value)}
+ />
+
+
+
+ Stromspeicher
+ setStorageCapacity(e.target.value)}
+ />
+
+
+
+ Preis pro kWh in €
+ setElectricityPrice(e.target.value)}
+ />
+
+
+
+
+ Eigenverbrauch: {selfConsumption} kWh
+ Jährliche Einsparungen: {annualSavings} €
+
+ >
+
+
+
+
+
+
+
+ >
)
}
From 4311205971ec00e530e4c5d8508c1565b1a91dc8 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 14:41:29 +0200
Subject: [PATCH 03/10] Use yield from pvSystem objects #242
---
.../PVSimulation/SavingsCalculation.js | 18 ++++++++++++++----
src/components/ThreeViewer/Overlay.js | 2 +-
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/components/PVSimulation/SavingsCalculation.js b/src/components/PVSimulation/SavingsCalculation.js
index c3c17102..adbae402 100644
--- a/src/components/PVSimulation/SavingsCalculation.js
+++ b/src/components/PVSimulation/SavingsCalculation.js
@@ -18,7 +18,7 @@ import React, { useState } from "react"
import { useTranslation } from "react-i18next"
import HoverHelp from "../Template/HoverHelp"
-function SavingCalculation({ PVSystems }) {
+function SavingCalculation({ pvSystems }) {
const { isOpen, onOpen, onClose } = useDisclosure({ defaultIsOpen: false })
const { t } = useTranslation()
const [annualConsumption, setAnnualConsumption] = useState("")
@@ -26,16 +26,23 @@ function SavingCalculation({ PVSystems }) {
const [electricityPrice, setElectricityPrice] = useState(0.25)
const [selfConsumption, setSelfConsumption] = useState(0)
const [annualSavings, setAnnualSavings] = useState(0)
+ let pvProduction
+ console.log("pvSystems", pvSystems)
+ if (pvSystems.length > 0) {
+ pvProduction = Math.round(
+ pvSystems.reduce((previous, current) => previous + current.annualYield, 0)
+ )
+ }
async function handleCalculateSaving() {
async function calculateSaving({
+ pvProduction,
consumptionHousehold,
storageCapacity,
electricityPrice,
setSelfConsumption,
setAnnualSavings,
}) {
- const pvProduction = 6000
const response = await fetch(
"https://www.openpv.de/data/savings_calculation/cons_prod.json"
)
@@ -97,6 +104,7 @@ function SavingCalculation({ PVSystems }) {
}
await calculateSaving({
+ pvProduction: pvProduction,
consumptionHousehold: parseFloat(annualConsumption),
storageCapacity: storageCapacity,
electricityPrice: electricityPrice,
@@ -106,11 +114,10 @@ function SavingCalculation({ PVSystems }) {
}
const initialRef = React.useRef(null)
- console.log("PVSystems", PVSystems)
return (
<>
- {PVSystems.length > 0 && (
+ {pvSystems.length > 0 && (
@@ -161,6 +168,9 @@ function SavingCalculation({ PVSystems }) {
+
+ Jährliche Stromerzeugung durch PV: {pvProduction} kWh
+
Eigenverbrauch: {selfConsumption} kWh
Jährliche Einsparungen: {annualSavings} €
diff --git a/src/components/ThreeViewer/Overlay.js b/src/components/ThreeViewer/Overlay.js
index dc58db82..3873c4f5 100644
--- a/src/components/ThreeViewer/Overlay.js
+++ b/src/components/ThreeViewer/Overlay.js
@@ -132,7 +132,7 @@ function Overlay({
/>
-
+
>
)
From efe166ca98c6960b2c9ca7c94b850b72e8427c99 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 14:43:05 +0200
Subject: [PATCH 04/10] Delete unnecessary logging #242
---
src/components/PVSimulation/SavingsCalculation.js | 6 ------
src/components/ThreeViewer/Meshes/PVSystems.js | 4 ----
src/simulation/main.js | 2 --
3 files changed, 12 deletions(-)
diff --git a/src/components/PVSimulation/SavingsCalculation.js b/src/components/PVSimulation/SavingsCalculation.js
index adbae402..fb6daf15 100644
--- a/src/components/PVSimulation/SavingsCalculation.js
+++ b/src/components/PVSimulation/SavingsCalculation.js
@@ -27,7 +27,6 @@ function SavingCalculation({ pvSystems }) {
const [selfConsumption, setSelfConsumption] = useState(0)
const [annualSavings, setAnnualSavings] = useState(0)
let pvProduction
- console.log("pvSystems", pvSystems)
if (pvSystems.length > 0) {
pvProduction = Math.round(
pvSystems.reduce((previous, current) => previous + current.annualYield, 0)
@@ -94,11 +93,6 @@ function SavingCalculation({ pvSystems }) {
0
)
- console.log(
- selfConsumedElectricity,
- "kWh are self consumed in the household"
- )
-
setSelfConsumption(Math.round(selfConsumedElectricity))
setAnnualSavings(Math.round(selfConsumedElectricity * electricityPrice))
}
diff --git a/src/components/ThreeViewer/Meshes/PVSystems.js b/src/components/ThreeViewer/Meshes/PVSystems.js
index 85f28508..f1036c0d 100644
--- a/src/components/ThreeViewer/Meshes/PVSystems.js
+++ b/src/components/ThreeViewer/Meshes/PVSystems.js
@@ -5,7 +5,6 @@ import * as BufferGeometryUtils from "three/addons/utils/BufferGeometryUtils.js"
import TextSprite from "../TextSprite"
export const PVSystems = ({ pvSystems }) => {
- console.log("PVSystems in three module", pvSystems)
return (
<>
{pvSystems.map((system, index) => (
@@ -145,7 +144,6 @@ export function createPVSystem({
annualYield: annualYield,
area: polygonArea,
}
- console.log("newPVSystem", newPVSystem)
setPVSystems((prevSystems) => [...prevSystems, newPVSystem])
setPVPoints([])
@@ -341,8 +339,6 @@ function filterPolygonsByDistance(geometry, points, threshold) {
}
}
- console.log("Filtered polygons:", filteredPolygons)
-
return filteredPolygons
}
diff --git a/src/simulation/main.js b/src/simulation/main.js
index a77aac78..d17f3f1f 100644
--- a/src/simulation/main.js
+++ b/src/simulation/main.js
@@ -48,7 +48,6 @@ export async function mainSimulation(location) {
? (numSimulations = window.numSimulations)
: (numSimulations = 80)
function loadingBarWrapperFunction(progress, total = 100) {
- // console.log("Simulation Progress is ", progress)
return window.setSimulationProgress(progress)
}
@@ -126,7 +125,6 @@ export async function simulationForNewBuilding(props) {
progressCallback: (progress, total) =>
console.log("Simulation Progress is ", progress),
})
- console.log("SimulationMesh", simulationMesh)
const material = new THREE.MeshLambertMaterial({
vertexColors: true,
side: THREE.DoubleSide,
From 5351b05fc4bc5ce35abe253aabfc6d6837a47ded Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 14:56:07 +0200
Subject: [PATCH 05/10] Delete outdated comment #242
---
src/pages/Simulation.js | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/src/pages/Simulation.js b/src/pages/Simulation.js
index fcbff248..139c7c23 100644
--- a/src/pages/Simulation.js
+++ b/src/pages/Simulation.js
@@ -33,12 +33,9 @@ function Index() {
surrounding: [],
background: [],
})
-
+ // highlighted meshes for resimulation
const [selectedMesh, setSelectedMesh] = useState([])
-
- // When a building is selected from the Surrounding to be simulated, it needs to be deleted
- // from the surrounding mesh. This state collects a list of names that should not be rendered
- // Elements are for example "SurroundingMesh-37"
+ // meshes that were simulated
const [simulationMeshes, setSimulationMeshes] = useState([])
window.setGeometries = setGeometries
From 19cbddefb522890a763ee51fd7b6f783dd8e9ca8 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 14:57:36 +0200
Subject: [PATCH 06/10] Move OverlayDrawPV to Overlay #242
---
src/components/ThreeViewer/Overlay.js | 55 +++++++++++++++++++
src/components/ThreeViewer/OverlayDrawPV.js | 58 ---------------------
2 files changed, 55 insertions(+), 58 deletions(-)
delete mode 100644 src/components/ThreeViewer/OverlayDrawPV.js
diff --git a/src/components/ThreeViewer/Overlay.js b/src/components/ThreeViewer/Overlay.js
index 3873c4f5..d05e5d4c 100644
--- a/src/components/ThreeViewer/Overlay.js
+++ b/src/components/ThreeViewer/Overlay.js
@@ -28,6 +28,7 @@ import SavingCalculation from "../PVSimulation/SavingsCalculation"
import ButtonWithHoverHelp from "../Template/ButtonWithHoverHelp"
import HoverHelp from "../Template/HoverHelp"
import SliderWithLabel from "../Template/SliderWithLabel"
+import { createPVSystem } from "./Meshes/PVSystems"
import OverlayDrawPV from "./OverlayDrawPV"
function Overlay({
@@ -295,3 +296,57 @@ const ModalControls = ({ isOpen, onClose }) => {
)
}
+
+function OverlayDrawPV({
+ setPVSystems,
+ pvPoints,
+ setPVPoints,
+ setFrontendState,
+ simulationMeshes,
+}) {
+ const { t } = useTranslation()
+ const handleCreatePVButtonClick = () => {
+ createPVSystem({
+ setPVSystems,
+ pvPoints,
+ setPVPoints,
+ simulationMeshes,
+ })
+ setFrontendState("Results")
+ }
+
+ const handleAbortButtonClick = () => {
+ setFrontendState("Results")
+ }
+
+ return (
+ <>
+
+ {pvPoints.length > 0 && (
+
+ )}
+
+ >
+ )
+}
diff --git a/src/components/ThreeViewer/OverlayDrawPV.js b/src/components/ThreeViewer/OverlayDrawPV.js
deleted file mode 100644
index b01ff422..00000000
--- a/src/components/ThreeViewer/OverlayDrawPV.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Button } from "@chakra-ui/react"
-import React from "react"
-import { useTranslation } from "react-i18next"
-import { createPVSystem } from "./Meshes/PVSystems"
-
-export default function OverlayDrawPV({
- setPVSystems,
- pvPoints,
- setPVPoints,
- setFrontendState,
- simulationMeshes,
-}) {
- const { t } = useTranslation()
- const handleCreatePVButtonClick = () => {
- createPVSystem({
- setPVSystems,
- pvPoints,
- setPVPoints,
- simulationMeshes,
- })
- setFrontendState("Results")
- }
-
- const handleAbortButtonClick = () => {
- setFrontendState("Results")
- }
-
- return (
- <>
-
- {pvPoints.length > 0 && (
-
- )}
-
- >
- )
-}
From 9b3d63f12510dc07f4ad9306e3485a547ecd6475 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 15:01:56 +0200
Subject: [PATCH 07/10] Delete import of moved component #242
---
src/components/ThreeViewer/Overlay.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/ThreeViewer/Overlay.js b/src/components/ThreeViewer/Overlay.js
index d05e5d4c..b5729615 100644
--- a/src/components/ThreeViewer/Overlay.js
+++ b/src/components/ThreeViewer/Overlay.js
@@ -29,7 +29,6 @@ import ButtonWithHoverHelp from "../Template/ButtonWithHoverHelp"
import HoverHelp from "../Template/HoverHelp"
import SliderWithLabel from "../Template/SliderWithLabel"
import { createPVSystem } from "./Meshes/PVSystems"
-import OverlayDrawPV from "./OverlayDrawPV"
function Overlay({
frontendState,
From 98e0f082acada179bf57bd53da92cc97bf6b7802 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 17:08:31 +0200
Subject: [PATCH 08/10] Change color schema again #242
---
src/simulation/main.js | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/simulation/main.js b/src/simulation/main.js
index d17f3f1f..8689d8e5 100644
--- a/src/simulation/main.js
+++ b/src/simulation/main.js
@@ -4,6 +4,9 @@ import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js
import { downloadBuildings } from "./download"
import { processGeometries } from "./preprocessing"
+const c0 = [0, 0.05, 0.2]
+const c1 = [1, 0.1, 0.1]
+
export async function mainSimulation(location) {
// Clear previous attributions if any
if (window.setAttribution) {
@@ -39,9 +42,7 @@ export async function mainSimulation(location) {
scene.addShadingGeometry(geom)
})
- scene.addColorMap(
- colormaps.interpolateTwoColors({ c0: [0.1, 0.2, 1], c1: [1, 1, 0.1] })
- )
+ scene.addColorMap(colormaps.interpolateTwoColors({ c0: c0, c1: c1 }))
let numSimulations
window.numSimulations
@@ -99,9 +100,7 @@ export async function simulationForNewBuilding(props) {
parseFloat(props.geoLocation.lat),
parseFloat(props.geoLocation.lon)
)
- shadingScene.addColorMap(
- colormaps.interpolateTwoColors({ c0: [0.1, 0.2, 1], c1: [1, 1, 0.1] })
- )
+ shadingScene.addColorMap(colormaps.interpolateTwoColors({ c0: c0, c1: c1 }))
shadingScene.addSimulationGeometry(newSimulationGeometries)
geometries.surrounding.forEach((geom) => {
shadingScene.addShadingGeometry(geom)
From 6a2d403dbf83e91274465df2dd4d8a9863d6c995 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 17:12:52 +0200
Subject: [PATCH 09/10] Change color of PV points #242
---
src/components/ThreeViewer/Points.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/ThreeViewer/Points.js b/src/components/ThreeViewer/Points.js
index a9f5c0aa..2f69f44a 100644
--- a/src/components/ThreeViewer/Points.js
+++ b/src/components/ThreeViewer/Points.js
@@ -8,7 +8,7 @@ const Points = ({ points }) => {
point.point,
])
const pointMaterial = new THREE.PointsMaterial({
- color: 0xff0000,
+ color: "#333333",
size: 5,
sizeAttenuation: false,
})
From 599b57ef90696da8f4d589de4535c89fe4280568 Mon Sep 17 00:00:00 2001
From: Florian Kotthoff <74312290+FlorianK13@users.noreply.github.com>
Date: Sat, 31 Aug 2024 17:16:44 +0200
Subject: [PATCH 10/10] Add disclaimer and translations #242
---
public/locales/de/translation.json | 17 +++++++
public/locales/en/translation.json | 17 +++++++
.../PVSimulation/SavingsCalculation.js | 46 ++++++++++++-------
3 files changed, 63 insertions(+), 17 deletions(-)
diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json
index 4dbee1b1..0226e631 100644
--- a/public/locales/de/translation.json
+++ b/public/locales/de/translation.json
@@ -94,5 +94,22 @@
"wheel": "Zwei Finger: Vergrößern und Verkleinern",
"doubleClick": "Zweimal kurz auf Gebäude tippen: Weiteres Gebäude für Simulation auswählen"
}
+ },
+ "savingsCalculation": {
+ "button": "Wirtschaftlichkeit der Anlage berechnen",
+ "consumptionTitle": "Jährlicher Stromverbrauch",
+ "consumptionHelper": "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.",
+ "consumptionPlaceholder": "Jährlicher Stromverbrauch in kWh",
+ "storageTitle": "Stromspeicher",
+ "storagePlaceholder": "Speicherkapazität in kWh",
+ "electricityPriceTitle": "Strompreis in cent",
+ "electricityPricePlaceholder": "Preis pro kWh in cent",
+ "disclaimer": "Die berechneten Erträge und Einsparungen dienen nur als grobe Orientierung. Die Angaben sind ohne Gewähr und ersetzen keine individuelle Berechnung und Beratung vor Ort!",
+ "results": {
+ "production": "Jährliche Stromerzeugung der Solaranlage: ",
+ "consumption": "Jährlicher Eigenverbrauch: ",
+ "savings": "Jährliche Einsparungen: "
+ },
+ "calculate": "Berechnen"
}
}
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index a7e50a28..ba0c8941 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -76,5 +76,22 @@
"wheel": "Two fingers: Zoom in and out",
"doubleClick": "Double-tap on a building: Select another building for simulation"
}
+ },
+ "savingsCalculation": {
+ "button": "Calculate Earnings",
+ "consumptionTitle": "Annual electricity consumption",
+ "consumptionHelper": "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.",
+ "consumptionPlaceholder": "Annual electricity consumption in kWh",
+ "storageTitle": "Electricity storage",
+ "storagePlaceholder": "Storage capacity in kWh",
+ "electricityPriceTitle": "Electricity price in cents",
+ "electricityPricePlaceholder": "Price per kWh in cents",
+ "disclaimer": "The calculated yields and savings are only for rough guidance. The information is without guarantee and does not replace individual calculation and on-site consultation!",
+ "results": {
+ "production": "Annual electricity generation of the solar system: ",
+ "consumption": "Annual self-consumption: ",
+ "savings": "Annual savings: "
+ },
+ "calculate": "Calculate"
}
}
diff --git a/src/components/PVSimulation/SavingsCalculation.js b/src/components/PVSimulation/SavingsCalculation.js
index fb6daf15..4bb93f35 100644
--- a/src/components/PVSimulation/SavingsCalculation.js
+++ b/src/components/PVSimulation/SavingsCalculation.js
@@ -11,6 +11,7 @@ import {
ModalFooter,
ModalHeader,
ModalOverlay,
+ Text,
UnorderedList,
useDisclosure,
} from "@chakra-ui/react"
@@ -23,7 +24,7 @@ function SavingCalculation({ pvSystems }) {
const { t } = useTranslation()
const [annualConsumption, setAnnualConsumption] = useState("")
const [storageCapacity, setStorageCapacity] = useState("")
- const [electricityPrice, setElectricityPrice] = useState(0.25)
+ const [electricityPrice, setElectricityPrice] = useState(25)
const [selfConsumption, setSelfConsumption] = useState(0)
const [annualSavings, setAnnualSavings] = useState(0)
let pvProduction
@@ -94,7 +95,9 @@ function SavingCalculation({ pvSystems }) {
)
setSelfConsumption(Math.round(selfConsumedElectricity))
- setAnnualSavings(Math.round(selfConsumedElectricity * electricityPrice))
+ setAnnualSavings(
+ Math.round((selfConsumedElectricity * electricityPrice) / 100)
+ )
}
await calculateSaving({
@@ -113,7 +116,7 @@ function SavingCalculation({ pvSystems }) {
<>
{pvSystems.length > 0 && (
)}
@@ -125,55 +128,64 @@ function SavingCalculation({ pvSystems }) {
<>
- Jährlicher Stromverbrauch{" "}
+ {t("savingsCalculation.consumptionTitle")}
setAnnualConsumption(e.target.value)}
/>
- Stromspeicher
+ {t("savingsCalculation.storageTitle")}
setStorageCapacity(e.target.value)}
/>
- Preis pro kWh in €
+
+ {t("savingsCalculation.electricityPriceTitle")}
+
setElectricityPrice(e.target.value)}
/>
+ {t("savingsCalculation.disclaimer")}
- Jährliche Stromerzeugung durch PV: {pvProduction} kWh
+ {t("savingsCalculation.results.production")}
+ {pvProduction} kWh
+
+
+ {t("savingsCalculation.results.consumption")}{" "}
+ {selfConsumption} kWh
+
+
+ {t("savingsCalculation.results.savings")} {annualSavings} €
- Eigenverbrauch: {selfConsumption} kWh
- Jährliche Einsparungen: {annualSavings} €
>
-