@@ -5,89 +5,103 @@ import Marker from 'react-leaflet-enhanced-marker';
55import Icon from "react-materialize/lib/Icon" ;
66
77class NeoTestReport extends NeoReport {
8+ // Per pixel, scaling factors for the latitude/longitude mapping function.
9+ widthScale = 3.35 ;
10+ heightScale = 6.7 ;
11+
812 constructor ( props ) {
913 super ( props ) ;
1014 this . state = { }
1115 }
1216
13- /**
14- * After the component mounts, build the D3 Visualization from the query results provided to the report.
15- */
16- componentDidMount ( ) {
17- let width = this . state . width ;
18- let height = this . state . height ;
1917
18+ recomputeMapInformation ( ) {
2019 this . state . width = this . props . clientWidth - 50 ; //-90 + props.width * 105 - xShift * 0.5;
2120 this . state . height = - 145 + this . props . height * 100 ;
22- let colors = [ "#588c7e" , "#f2e394" , "#f2ae72" , "#d96459" , "#5b9aa0" , "#d6d4e0" , "#b8a9c9" , "#622569" , "#ddd5af" , "#d9ad7c" , "#a2836e" , "#674d3c" , "grey" ]
2321
24- if ( width !== this . props . clientWidth - 50 || height !== - 145 + this . props . height * 100 ) {
25- let nodesAndPositions = [
26- {
27- pos : [ 51.4972055 , 4.4801085 ] ,
28- node : {
29- id : 4
22+ this . state . nodesAndPositions = [ ]
23+ if ( this . state . data ) {
24+ this . state . data . forEach ( record => {
25+ Object . values ( record ) . forEach ( v => {
26+ if ( v . identity && v . properties ) {
27+ console . log ( v )
28+ Object . values ( v . properties ) . forEach ( p => {
29+ if ( p . srid && p . x && p . y ) {
30+ console . log ( [ p . x , p . y ] )
31+ this . state . nodesAndPositions . push ( { pos : [ p . y , p . x ] , node : v . properties } )
32+ }
33+ } )
3034 }
31- } ,
32- {
33- pos : [ 51.4472055 , 4.4601085 ] ,
34- node : {
35- id : 6
36- }
37- } ]
38- ;
39- let xPositions = nodesAndPositions . map ( i => i . pos [ 0 ] ) ;
40- let yPositions = nodesAndPositions . map ( i => i . pos [ 1 ] ) ;
41- let centerX = xPositions . reduce ( ( a , b ) => a + b , 0 ) / nodesAndPositions . length ;
42- let centerY = yPositions . reduce ( ( a , b ) => a + b , 0 ) / nodesAndPositions . length ;
43- // let minX = Math.min.apply(null, xPositions);
44- let maxX = Math . max . apply ( null , xPositions ) ;
45- // let minY = Math.min.apply(null, yPositions);
46- let maxY = Math . max . apply ( null , yPositions ) ;
47- // Build map objects
48- let markers = nodesAndPositions . map ( i =>
49- < Marker position = { i . pos } icon = { < div style = { { color : colors [ 0 ] } } > < Icon className = "close" > place</ Icon > </ div > } >
50- < Popup > { JSON . stringify ( i . node ) } </ Popup >
51- </ Marker > )
52- let lines = [ < Polyline key = { 0 } positions = { [ [ 51.4972055 , 4.4801085 ] , [ 51.4472055 , 4.4601085 ] ] } color = { colors [ 0 ] } /> ] ;
53-
54- // Set visualization object
55- this . state . visualization =
56- < MapContainer key = { 0 } style = { { "width" : this . state . width + "px" , "height" : this . state . height + "px" } }
57- center = {
58- [
59- centerX ,
60- centerY
61- ]
62- } zoom = { 13 }
63- scrollWheelZoom = { false } >
64- < TileLayer
65- attribution = '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
66- url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
67- />
68- { markers }
69- { lines }
70- </ MapContainer > ;
71- this . forceUpdate ( ) ;
35+ } )
36+
37+ } )
7238 }
73- }
7439
75- /**
76- * After the component updates, remount and reset the visualization with the newly retrieved data.
77- */
78- componentDidUpdate ( prevProps ) {
79- super . componentDidUpdate ( prevProps ) ;
80- this . componentDidMount ( ) ;
40+ // This is where math happens - we try to come up with the optimal zoom to fit all rendered nodes...
41+ let longitudePositions = this . state . nodesAndPositions . map ( i => i . pos [ 0 ] + 180 ) ;
42+ this . state . centerLongitude = longitudePositions . reduce ( ( a , b ) => a + b , 0 ) / this . state . nodesAndPositions . length ;
43+ let maxLong = Math . max . apply ( null , longitudePositions ) ;
44+ if ( ( maxLong === this . state . centerLongitude ) ) {
45+ maxLong += 0.000000001 ;
46+ }
47+ let longHeightScaleFactor = this . state . height / this . heightScale ;
48+ let longDiff = maxLong - this . state . centerLongitude ;
49+ let longProjectedHeight = longDiff / longHeightScaleFactor ;
50+ let longZoomFit = Math . ceil ( Math . log2 ( 1.0 / longProjectedHeight ) ) ;
51+
52+
53+ let latitudePositions = this . state . nodesAndPositions . map ( i => i . pos [ 1 ] + 90 ) ;
54+ this . state . centerLatitude = latitudePositions . reduce ( ( a , b ) => a + b , 0 ) / this . state . nodesAndPositions . length ;
55+ let maxLat = Math . max . apply ( null , latitudePositions ) ;
56+ if ( ( maxLat === this . state . centerLatitude ) ) {
57+ maxLat += 0.000000001 ;
58+ }
59+ let latWidthScaleFactor = this . state . width / this . widthScale ;
60+ let latDiff = maxLat - this . state . centerLatitude ;
61+ let latProjectedWidth = latDiff / latWidthScaleFactor ;
62+ let latZoomFit = Math . ceil ( Math . log2 ( 1.0 / latProjectedWidth ) ) ;
63+
64+ // Choose a zoom factor that fits, based on the difference between lat and long.
65+ this . state . zoom = Math . min ( latZoomFit , longZoomFit ) ;
66+
8167 }
8268
69+
70+
8371 render ( ) {
8472 let rendered = super . render ( ) ;
8573
8674 if ( rendered ) {
8775 return rendered ;
8876 }
89- return this . state . visualization ;
90- // return <p>{JSON.stringify(this.state.data)}</p>;
77+
78+ this . recomputeMapInformation ( ) ;
79+ let colors = [ "#588c7e" , "#f2e394" , "#f2ae72" , "#d96459" , "#5b9aa0" , "#d6d4e0" , "#b8a9c9" , "#622569" , "#ddd5af" , "#d9ad7c" , "#a2836e" , "#674d3c" , "grey" ]
80+ let markers = ( this . state . nodesAndPositions ) ?
81+ this . state . nodesAndPositions . map ( i =>
82+ < Marker position = { i . pos }
83+ icon = { < div style = { { color : colors [ 0 ] } } > < Icon className = "close" > place</ Icon > </ div > } >
84+ < Popup > < code > { Object . keys ( i . node ) . map ( key => < pre > { key + ": " + i . node [ key ] + "\n" } </ pre > ) } </ code > </ Popup >
85+ </ Marker > ) : < div > </ div >
86+ let lines = < div > </ div > // [<Polyline key={0} positions={[this.state.pos1, this.state.pos2]} color={colors[0]}/>];
87+
88+ return < MapContainer key = { 0 } style = { { "width" : this . state . width + "px" , "height" : this . state . height + "px" } }
89+ center = {
90+ [
91+ ( this . state . centerLongitude ) ? this . state . centerLongitude - 180 : 0 ,
92+ ( this . state . centerLatitude ) ? this . state . centerLatitude - 90 : 0
93+ ]
94+ }
95+ zoom = { ( this . state . zoom ) ? this . state . zoom : 0 }
96+ maxZoom = { 18 }
97+ scrollWheelZoom = { false } >
98+ < TileLayer
99+ attribution = '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
100+ url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
101+ />
102+ { markers }
103+ { lines }
104+ </ MapContainer > ;
91105 }
92106}
93107
0 commit comments