Skip to content

Commit 78a7d43

Browse files
committed
Better map visualizations...
1 parent 2a39e70 commit 78a7d43

File tree

3 files changed

+92
-71
lines changed

3 files changed

+92
-71
lines changed

public/style.css

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ body {
1616
transform: translateY(-18px) scale(0.8);
1717
}
1818

19-
.select-dropdown {
19+
.card-reveal .select-dropdown {
2020
top: 0px !important;
2121
}
22-
22+
.card-action .select-dropdown {
23+
bottom: 0px !important;
24+
top: auto !important;
25+
}
2326
.log {
2427
background-color: lightgrey;
2528
font-size: 12px;
@@ -155,7 +158,10 @@ code {
155158
margin-top: 150px;
156159
margin-bottom: 150px;
157160
}
158-
161+
.card-action {
162+
max-height: 150px;
163+
overflow-y: scroll;
164+
}
159165
.btn-center-align :hover {
160166
opacity: 0.7;
161167
}
@@ -183,9 +189,6 @@ code {
183189
min-width: 60px;
184190
}
185191

186-
.card-action {
187-
max-height: 200px;
188-
}
189192

190193
.card-action .pagination a {
191194
color: #000 !important;
@@ -333,7 +336,12 @@ nav textarea:disabled {
333336
.leaflet-control-attribution {
334337
font-size: 8px !important;
335338
}
336-
339+
.leaflet-popup-content {
340+
width: auto !important;
341+
}
342+
.leaflet-popup-content pre{
343+
margin: 0px;
344+
}
337345
.select-wrapper {
338346
width: 140px;
339347
}

src/card/footer/NeoGraphVisFooter.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class NeoGraphVisFooter extends NeoFooter {
4747
options={null}
4848
style={{
4949
backgroundColor: colors[index % colors.length],
50-
display: (index < this.props.width * 3.5 || this.props.width == 12) ? "inline-block" : "none",
5150
color: 'white'
5251
}}
5352
>

src/card/report/NeoMapReport.js

Lines changed: 77 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,89 +5,103 @@ import Marker from 'react-leaflet-enhanced-marker';
55
import Icon from "react-materialize/lib/Icon";
66

77
class 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='&copy; <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='&copy; <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

Comments
 (0)