@@ -40,7 +40,7 @@ import { LinearInterpolator, FlyToInterpolator } from 'deck.gl';
40
40
import { HeatmapLayer } from 'deck.gl' ;
41
41
import { InvertColorsOff , ShopTwoOutlined } from '@mui/icons-material' ;
42
42
43
- import { getCountyNodes , ExtractFirstTimeSlice , ExtractFlowData , getBarNet , getPoints , getGeneration , getLoad , getContours } from "./src/dataprocess" ;
43
+ import { getCountyNodes , ExtractFirstTimeSlice , ExtractFlowData , getBarNet , getPoints , getGeneration , getLoad , getContours , getAreas , getZones } from "./src/dataprocess" ;
44
44
import { LineColor , FlowColor , FillColor , fillGenColumnColor , fillGenColumnColorCap , getVoltageFillColor } from "./src/color"
45
45
46
46
import 'core-js/actual/structured-clone' ;
@@ -72,6 +72,9 @@ var data = ExtractFirstTimeSlice(geodata);
72
72
const countyloaddata = getCountyNodes ( data ) ;
73
73
data = countyloaddata . updatedata ;
74
74
75
+ const areas = getAreas ( casedata ) ;
76
+
77
+ const zones = getZones ( casedata ) ;
75
78
76
79
const flowdata = ExtractFlowData ( data ) ;
77
80
@@ -146,9 +149,15 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
146
149
const [ busNameSelectItems , setBusNameSelectItems ] = useState ( [ ] ) ;
147
150
148
151
const [ busNameItems , setbusNameItems ] = useState ( data . features
149
- . filter ( f => f . geometry . type == "Point" ) . map ( ( f ) => ( f . properties . NAME ) ) ) ;
152
+ . filter ( f => f . geometry . type == "Point" ) . map ( ( f ) => ( f . properties . NAME ) ) ) ;
153
+
154
+ const [ areaNameSelectItems , setAreaNameSelectItems ] = useState ( [ ] ) ;
150
155
156
+ const [ areaNameItems , setAreaNameItems ] = useState ( areas . features . map ( f => f . properties . name ) ) ;
151
157
158
+ const [ zoneNameSelectItems , setZoneNameSelectItems ] = useState ( [ ] ) ;
159
+
160
+ const [ zoneNameItems , setZoneNameItems ] = useState ( zones . features . map ( f => f . properties . name ) ) ;
152
161
153
162
const [ countyNameSelectItems , setCountyNameSelectItems ] = useState ( [ ] ) ;
154
163
@@ -430,6 +439,54 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
430
439
431
440
} ) ;
432
441
442
+ const zoomToAreaName = useCallback ( ( filterareas , minLng , minLat , maxLng , maxLat ) => {
443
+ var viewport = new WebMercatorViewport ( INITIAL_VIEW_STATE ) ;
444
+
445
+ const { longitude, latitude, zoom } = viewport . fitBounds ( [ [ minLng , minLat ] , [ maxLng , maxLat ] ] ) ;
446
+
447
+ setInitialViewState ( viewState => ( {
448
+ ...viewState ,
449
+ latitude : latitude ,
450
+ longitude : longitude ,
451
+ pitch : 50 ,
452
+ traansitionInterpolator : transitionFlyToInterpolator ,
453
+ transitionDuration : 5000 ,
454
+ zoom : 7.5 ,
455
+ onTransitionEnd : activatePopup
456
+ } ) )
457
+
458
+ var popup = { display : false , name : '' , info : '' } ; // Will be displayed after transition end only
459
+ popup . name = "Area " + filterareas . properties . name ;
460
+ // popup.info = "Area: " + info.object.properties.name;
461
+ setShowPopup ( showPopup => ( { ...showPopup , ...popup } ) ) ;
462
+
463
+ } ) ;
464
+
465
+ const zoomToZoneName = useCallback ( ( filterzones , minLng , minLat , maxLng , maxLat ) => {
466
+ var viewport = new WebMercatorViewport ( INITIAL_VIEW_STATE ) ;
467
+
468
+ const { longitude, latitude, zoom } = viewport . fitBounds ( [ [ minLng , minLat ] , [ maxLng , maxLat ] ] ) ;
469
+
470
+ setInitialViewState ( viewState => ( {
471
+ ...viewState ,
472
+ latitude : latitude ,
473
+ longitude : longitude ,
474
+ pitch : 50 ,
475
+ traansitionInterpolator : transitionFlyToInterpolator ,
476
+ transitionDuration : 5000 ,
477
+ zoom : 7.5 ,
478
+ onTransitionEnd : activatePopup
479
+ } ) )
480
+
481
+ var popup = { display : false , name : '' , info : '' } ; // Will be displayed after transition end only
482
+ popup . name = "Zone " + filterzones . properties . name ;
483
+ // popup.info = "Zone: " + info.object.properties.name;
484
+ setShowPopup ( showPopup => ( { ...showPopup , ...popup } ) ) ;
485
+
486
+ } ) ;
487
+
488
+
489
+
433
490
const zoomToCounty = useCallback ( ( info ) => {
434
491
if ( ! info ) return null ;
435
492
@@ -456,7 +513,73 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
456
513
457
514
var popup = { display : false , name : '' , info : '' } ; // Will be displayed after transition end only
458
515
popup . name = info . object . properties . NAME ;
459
- popup . info = "Load: " + info . object . properties . Pd . toFixed ( 2 ) + "MW" ;
516
+ popup . info = "Load loss: " + info . object . properties . Pd . toFixed ( 2 ) + "MW" ;
517
+ setShowPopup ( showPopup => ( { ...showPopup , ...popup } ) ) ;
518
+
519
+
520
+ }
521
+ } ) ;
522
+
523
+ const zoomToArea = useCallback ( ( info ) => {
524
+ if ( ! info ) return null ;
525
+
526
+ if ( info . layer . id == 'AreaLayer' ) {
527
+ var layer = info . layer ;
528
+ var { viewport } = layer . context ;
529
+
530
+ var cbounds = bbox ( info . object ) ;
531
+ var c1 = [ cbounds [ 0 ] , cbounds [ 1 ] ] ;
532
+ var c2 = [ cbounds [ 2 ] , cbounds [ 3 ] ] ;
533
+ var areabounds = [ c1 , c2 ] ;
534
+ const { longitude, latitude, zoom } = viewport . fitBounds ( areabounds ) ;
535
+
536
+ setInitialViewState ( viewState => ( {
537
+ ...viewState ,
538
+ latitude : latitude ,
539
+ longitude : longitude ,
540
+ pitch : 50 ,
541
+ traansitionInterpolator : transitionFlyToInterpolator ,
542
+ transitionDuration : 5000 ,
543
+ zoom : zoom - 0.25 ,
544
+ onTransitionEnd : activatePopup
545
+ } ) )
546
+
547
+ var popup = { display : false , name : '' , info : '' } ; // Will be displayed after transition end only
548
+ popup . name = "Area " + info . object . properties . name ;
549
+ // popup.info = "Area: " + info.object.properties.name;
550
+ setShowPopup ( showPopup => ( { ...showPopup , ...popup } ) ) ;
551
+
552
+
553
+ }
554
+ } ) ;
555
+
556
+ const zoomToZone = useCallback ( ( info ) => {
557
+ if ( ! info ) return null ;
558
+
559
+ if ( info . layer . id == 'ZoneLayer' ) {
560
+ var layer = info . layer ;
561
+ var { viewport } = layer . context ;
562
+
563
+ var cbounds = bbox ( info . object ) ;
564
+ var c1 = [ cbounds [ 0 ] , cbounds [ 1 ] ] ;
565
+ var c2 = [ cbounds [ 2 ] , cbounds [ 3 ] ] ;
566
+ var zonebounds = [ c1 , c2 ] ;
567
+ const { longitude, latitude, zoom } = viewport . fitBounds ( zonebounds ) ;
568
+
569
+ setInitialViewState ( viewState => ( {
570
+ ...viewState ,
571
+ latitude : latitude ,
572
+ longitude : longitude ,
573
+ pitch : 50 ,
574
+ traansitionInterpolator : transitionFlyToInterpolator ,
575
+ transitionDuration : 5000 ,
576
+ zoom : zoom - 0.25 ,
577
+ onTransitionEnd : activatePopup
578
+ } ) )
579
+
580
+ var popup = { display : false , name : '' , info : '' } ; // Will be displayed after transition end only
581
+ popup . name = "Zone " + info . object . properties . name ;
582
+ // popup.info = "Zone: " + info.object.properties.name;
460
583
setShowPopup ( showPopup => ( { ...showPopup , ...popup } ) ) ;
461
584
462
585
@@ -487,10 +610,9 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
487
610
const [ genlayeractive , setGenLayerActive ] = useState ( false ) ;
488
611
const [ genlayercapactive , setGenLayerCapActive ] = useState ( false ) ;
489
612
const [ voltagelayeractive , setVoltageLayerActive ] = useState ( false ) ;
490
-
491
-
492
-
493
-
613
+ const [ zonelayeractive , setZoneLayerActive ] = useState ( false ) ;
614
+ const [ arealayeractive , setAreaLayerActive ] = useState ( false ) ;
615
+
494
616
const handleUserInput = ( inputText ) => {
495
617
console . log ( `New message incoming! ${ inputText } ` ) ;
496
618
// Now send the message to GPT and get response
@@ -612,6 +734,31 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
612
734
} ) ) )
613
735
} ;
614
736
737
+ const handleAreaLayerChange = ( event ) => {
738
+ setAreaLayerActive ( event . target . checked ) ;
739
+ // setVoltageFilterValue([0.89, 1.11]);
740
+
741
+ event . target . checked && ( setInitialViewState ( viewState => ( {
742
+ ...viewState ,
743
+ pitch : 40 ,
744
+ traansitionInterpolator : transitionFlyToInterpolator ,
745
+ transitionDuration : 2000 ,
746
+ } ) ) )
747
+ } ;
748
+
749
+ const handleZoneLayerChange = ( event ) => {
750
+ setZoneLayerActive ( event . target . checked ) ;
751
+ // setVoltageFilterValue([0.89, 1.11]);
752
+
753
+ event . target . checked && ( setInitialViewState ( viewState => ( {
754
+ ...viewState ,
755
+ pitch : 40 ,
756
+ traansitionInterpolator : transitionFlyToInterpolator ,
757
+ transitionDuration : 2000 ,
758
+ } ) ) )
759
+ } ;
760
+
761
+
615
762
const handleGenLayerChange = ( event ) => {
616
763
setGenLayerActive ( event . target . checked ) ;
617
764
setGenFilterValue ( [ gendata . minPg , gendata . maxPg ] ) ;
@@ -910,6 +1057,59 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
910
1057
}),
911
1058
*/
912
1059
1060
+
1061
+ new GeoJsonLayer ( {
1062
+ id : 'AreaLayer' ,
1063
+ data : areas ,
1064
+ pickable : arealayeractive ,
1065
+ visible : arealayeractive ,
1066
+ stroked : true ,
1067
+ filled : true ,
1068
+ extruded : true ,
1069
+ wireframe : true ,
1070
+ lineWidthMinPixels : 1 ,
1071
+ getPolygon : d => d . geometry . coordinates ,
1072
+ // getElevation: d => d.properties.Pd*5.0,
1073
+ getFillColor : [ 255 , 192 , 203 ] ,
1074
+ getLineColor : [ 80 , 80 , 80 ] ,
1075
+ getLineWidth : d => 1 ,
1076
+ opacity : 0.1 ,
1077
+ onClick : zoomToArea ,
1078
+ // extensions: [new DataFilterExtension({ filtersize: 1 })],
1079
+ // getFilterValue: getLoadFilterValue,
1080
+ // filterRange: loadfiltervalue,
1081
+
1082
+ // updateTriggers: {
1083
+ // getFilterValue: [netfiltervalue, countyNameSelectItems]
1084
+ // }
1085
+ } ) ,
1086
+
1087
+ new GeoJsonLayer ( {
1088
+ id : 'ZoneLayer' ,
1089
+ data : zones ,
1090
+ pickable : zonelayeractive ,
1091
+ visible : zonelayeractive ,
1092
+ stroked : true ,
1093
+ filled : true ,
1094
+ extruded : true ,
1095
+ wireframe : true ,
1096
+ lineWidthMinPixels : 1 ,
1097
+ getPolygon : d => d . geometry . coordinates ,
1098
+ // getElevation: d => d.properties.Pd*5.0,
1099
+ getFillColor : [ 252 , 245 , 95 ] ,
1100
+ getLineColor : [ 80 , 80 , 80 ] ,
1101
+ getLineWidth : d => 1 ,
1102
+ opacity : 0.1 ,
1103
+ onClick : zoomToZone ,
1104
+ // extensions: [new DataFilterExtension({ filtersize: 1 })],
1105
+ // getFilterValue: getLoadFilterValue,
1106
+ // filterRange: loadfiltervalue,
1107
+
1108
+ // updateTriggers: {
1109
+ // getFilterValue: [netfiltervalue, countyNameSelectItems]
1110
+ // }
1111
+ } ) ,
1112
+
913
1113
new GeoJsonLayer ( {
914
1114
id : 'PolygonLayerload' ,
915
1115
data : countyload ,
@@ -1104,6 +1304,56 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
1104
1304
}
1105
1305
}
1106
1306
1307
+ const handleAreaMultiselect = ( selectItem , metadata ) => {
1308
+
1309
+ const selected = areaNameSelectItems . indexOf ( metadata . dataItem )
1310
+ console . log ( selected ) ;
1311
+ if ( selected >= 0 ) { //if is selected, remove
1312
+ const newArray = [ ...areaNameSelectItems . slice ( 0 , selected ) , ...areaNameSelectItems . slice ( selected + 1 ) ] ;
1313
+ setAreaNameSelectItems ( newArray )
1314
+
1315
+ } else { //add to array
1316
+ setAreaNameSelectItems ( areaNameSelectItems => ( [ ...areaNameSelectItems , metadata . dataItem ] ) )
1317
+ const filterareas = areas . features . filter ( area => area . properties . name === metadata . dataItem )
1318
+ if ( filterareas . length > 0 ) {
1319
+ const longs = filterareas [ 0 ] . geometry . coordinates [ 0 ] . map ( d => d [ 0 ] )
1320
+ const lats = filterareas [ 0 ] . geometry . coordinates [ 0 ] . map ( d => d [ 1 ] )
1321
+ const minLng = Math . min ( ...longs )
1322
+ const maxLng = Math . max ( ...longs )
1323
+ const minLat = Math . min ( ...lats )
1324
+ const maxLat = Math . max ( ...lats )
1325
+
1326
+ zoomToAreaName ( filterareas [ 0 ] , minLng , minLat , maxLng , maxLat )
1327
+ }
1328
+ }
1329
+ }
1330
+
1331
+ const handleZoneMultiselect = ( selectItem , metadata ) => {
1332
+
1333
+ const selected = zoneNameSelectItems . indexOf ( metadata . dataItem )
1334
+ console . log ( selected ) ;
1335
+ if ( selected >= 0 ) { //if is selected, remove
1336
+ const newArray = [ ...zoneNameSelectItems . slice ( 0 , selected ) , ...zoneNameSelectItems . slice ( selected + 1 ) ] ;
1337
+ setZoneNameSelectItems ( newArray )
1338
+
1339
+ } else { //add to array
1340
+ setZoneNameSelectItems ( zoneNameSelectItems => ( [ ...zoneNameSelectItems , metadata . dataItem ] ) )
1341
+ const filterzones = zones . features . filter ( area => area . properties . name === metadata . dataItem )
1342
+ if ( filterzones . length > 0 ) {
1343
+ const longs = filterzones [ 0 ] . geometry . coordinates [ 0 ] . map ( d => d [ 0 ] )
1344
+ const lats = filterzones [ 0 ] . geometry . coordinates [ 0 ] . map ( d => d [ 1 ] )
1345
+ const minLng = Math . min ( ...longs )
1346
+ const maxLng = Math . max ( ...longs )
1347
+ const minLat = Math . min ( ...lats )
1348
+ const maxLat = Math . max ( ...lats )
1349
+
1350
+ zoomToZoneName ( filterzones [ 0 ] , minLng , minLat , maxLng , maxLat )
1351
+ }
1352
+ }
1353
+ }
1354
+
1355
+
1356
+
1107
1357
const renderItem = ( {
1108
1358
id,
1109
1359
name
@@ -1477,6 +1727,44 @@ export default function App({ refdata = data, refflowdata = flowdata, ggdata = g
1477
1727
</ AccordionDetails >
1478
1728
</ Accordion >
1479
1729
1730
+ < Accordion defaultExpanded = { false } >
1731
+ < AccordionSummary style = { { height : "20px" , minHeight : "30px" , paddingRight : "40px" , paddingLeft : "0px" } }
1732
+ expandIcon = { < ArrowDropDownIcon /> } >
1733
+ < Typography >
1734
+ < Checkbox checked = { arealayeractive } style = { { color : "primary" } } onChange = { handleAreaLayerChange } /> Show Areas
1735
+ </ Typography >
1736
+ </ AccordionSummary >
1737
+ < AccordionDetails >
1738
+ < Typography component = "div" >
1739
+ { arealayeractive && ( < div style = { { paddingRight : "40px" } } > < Multiselect
1740
+ defaultValue = { areaNameSelectItems }
1741
+ data = { areaNameItems }
1742
+ placeholder = { 'Search for areas' }
1743
+ onChange = { handleAreaMultiselect }
1744
+ /> </ div > ) }
1745
+ </ Typography >
1746
+ </ AccordionDetails >
1747
+ </ Accordion >
1748
+
1749
+ < Accordion defaultExpanded = { false } >
1750
+ < AccordionSummary style = { { height : "20px" , minHeight : "30px" , paddingRight : "40px" , paddingLeft : "0px" } }
1751
+ expandIcon = { < ArrowDropDownIcon /> } >
1752
+ < Typography >
1753
+ < Checkbox checked = { zonelayeractive } style = { { color : "primary" } } onChange = { handleZoneLayerChange } /> Show Zones
1754
+ </ Typography >
1755
+ </ AccordionSummary >
1756
+ < AccordionDetails >
1757
+ < Typography component = "div" >
1758
+ { zonelayeractive && ( < div style = { { paddingRight : "40px" } } > < Multiselect
1759
+ defaultValue = { zoneNameSelectItems }
1760
+ data = { zoneNameItems }
1761
+ placeholder = { 'Search for zones' }
1762
+ onChange = { handleZoneMultiselect }
1763
+ /> </ div > ) }
1764
+ </ Typography >
1765
+ </ AccordionDetails >
1766
+ </ Accordion >
1767
+
1480
1768
</ div >
1481
1769
1482
1770
{ /* <br></br> */ }
0 commit comments