Kate speckle poc (#7)
* 3d demos * url_constructor_demo * readme update * troubleshooting * formatting * formatting * readme * . * readme * readme * fix titles * colors with opacity * demo3d * fix mesh split * maptalks_fixed geometry * vertical coords * 3d display * building example * print * demos
This commit is contained in:
@@ -39,19 +39,72 @@ Example: [https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/pr
|
||||
List of possible issues you can experience and solutions to them:
|
||||
|
||||
- Page or Map stays blank and Developer Tools Console shows "net::ERR_QUIC_PROTOCOL_ERROR 200 (OK)"
|
||||
|
||||
Solution: Try reloading the page. Otherwise, if in Google Chrome, navigate to chrome://flags/#enable-quic in and change Experimental QUIC Protocol dropdown to Disabled.
|
||||
|
||||
- Model seems to be loaded incomplete
|
||||
|
||||
Solution: Check the message "feature count limited to ..." next to the Model name on the top of the page. If the message is present, try increasing the feature limit using "&limit=10000" URL parameter
|
||||
|
||||
- Attribute table doesn't have original feature attributes and properties
|
||||
Enable the URL parameter "&preserveAttributes=true". It is disabled by default due to the faulty display of the 3-dimentional multiPolygons overlapping themselves in 2d space, when viweving in the browser on 2d map. Enabling this parameter might make the multipolygons appear "transparent" due to self-overlap.
|
||||
|
||||
Report any other issues here or on our [Community Forum](https://speckle.community/invites/qxEmQb1QcM).
|
||||
Solution: Enable the URL parameter "&preserveAttributes=true". It is disabled by default due to the faulty display of the 3-dimentional multiPolygons overlapping themselves in 2d space, when viweving in the browser on 2d map. Enabling this parameter might make the multipolygons appear "transparent" due to self-overlap.
|
||||
|
||||
### Add Speckle Feature Layer to a web-based map
|
||||
Report any other issues here or on our [Community Forum](https://speckle.community/).
|
||||
|
||||
Check out the examples in 'speckle_demos' folder for Leaflet and OpenLayers implementation.
|
||||
## Add Speckle Feature Layers to web-based maps and desktop apps
|
||||
|
||||
### Add Speckle layer in Javascript
|
||||
|
||||
Javascript-based mapping libraries can load speckle data as JSON using the following function:
|
||||
|
||||
```javascript
|
||||
async function loadSpeckleData() => {
|
||||
var speckle_model_url = 'https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=polygons';
|
||||
const speckle_data = await fetch(speckle_model_url, {
|
||||
headers: {'Accept': 'application/geo+json'}
|
||||
}).then(response => response.json());
|
||||
}
|
||||
```
|
||||
|
||||
Then you can add it to the base map (e.g. using Leaflet and OpenStreetMap basemap tiles). The following example assumes an html div element with id="items-map":
|
||||
|
||||
```html
|
||||
<script>
|
||||
var map = L.map('items-map').setView([ 45 , -75 ], 5);
|
||||
map.addLayer(new L.TileLayer(
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 22,
|
||||
attribution: '© <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a> © Data: <a href="https://speckle.systems/">Speckle Systems</a>'
|
||||
}
|
||||
));
|
||||
loadSpeckleData();
|
||||
|
||||
async function loadSpeckleData() => {
|
||||
var speckle_model_url = 'https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=polygons';
|
||||
const speckle_data = await fetch(speckle_model_url, {
|
||||
headers: {'Accept': 'application/geo+json'}
|
||||
}).then(response => response.json());
|
||||
|
||||
speckle_layer = L.geoJSON(speckle_data, {
|
||||
onEachFeature: function (feature, layer) {
|
||||
layer.setStyle({
|
||||
fillColor: feature.displayProperties['color'],
|
||||
color: myFillColor,
|
||||
fillOpacity: 0.8,
|
||||
weight: feature.displayProperties['lineWidth'],
|
||||
radius: feature.displayProperties['radius']
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
speckle_layer.addTo(map);
|
||||
map.fitBounds(speckle_layer.getBounds())
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
Check out 'speckle_demos' folder for more Leaflet and OpenLayers implementation.
|
||||
|
||||
### Add Speckle WFS layer in QGIS
|
||||
1. Add new WFS Layer
|
||||
|
||||
@@ -88,13 +88,16 @@ def get_config(raw: bool = False, request: Request = None) -> dict:
|
||||
# make sure to restrict the usage for the key
|
||||
if ".speckle.systems" in request.url.split("?")[0] and map_api_key_speckle and len(map_api_key_speckle)>=20:
|
||||
CONFIG["server"]["map"]["url"] = r'https://api.maptiler.com/maps/dataviz/{z}/{x}/{y}.png' + f'?key={map_api_key_speckle}'
|
||||
CONFIG["server"]["map"]["key"] = f'{map_api_key_speckle}'
|
||||
CONFIG["server"]["map"]["attribution"] = r'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>'
|
||||
|
||||
elif map_api_key_local and len(map_api_key_local)>=20:
|
||||
CONFIG["server"]["map"]["url"] = r'https://api.maptiler.com/maps/dataviz/{z}/{x}/{y}.png' + f'?key={map_api_key_local}'
|
||||
CONFIG["server"]["map"]["key"] = f'{map_api_key_local}'
|
||||
CONFIG["server"]["map"]["attribution"] = r'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>'
|
||||
else:
|
||||
CONFIG["server"]["map"]["url"] = r'https://tile.openstreetmap.org/{z}/{x}/{y}.png'
|
||||
CONFIG["server"]["map"]["key"] = ""
|
||||
CONFIG["server"]["map"]["attribution"] = r'© <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
|
||||
|
||||
|
||||
|
||||
@@ -51,10 +51,11 @@ def separate_display_vals(displayValue: List) -> List[Tuple["Base"]]:
|
||||
|
||||
for i, item in enumerate(displayValue):
|
||||
if isinstance(item, Mesh):
|
||||
|
||||
count = 0
|
||||
all_count = len(item.faces)
|
||||
|
||||
for _ in item.faces:
|
||||
try:
|
||||
if count < all_count:
|
||||
faces = []
|
||||
verts = []
|
||||
colors = []
|
||||
@@ -71,20 +72,16 @@ def separate_display_vals(displayValue: List) -> List[Tuple["Base"]]:
|
||||
new_vert = item.vertices[3*vert_index : 3*vert_index + 3]
|
||||
verts.extend(new_vert)
|
||||
|
||||
if isinstance(item.colors, List) and len(item.colors)>2:
|
||||
|
||||
if isinstance(item.colors, List) and len(item.colors) > vert_index:
|
||||
color = item.colors[vert_index]
|
||||
colors.append(color)
|
||||
|
||||
count += vert_num+1
|
||||
except IndexError:
|
||||
continue
|
||||
|
||||
if len(colors)>0:
|
||||
mesh = Mesh.create(faces= faces, vertices=verts, colors=colors)
|
||||
else:
|
||||
mesh = Mesh.create(faces= faces, vertices=verts)
|
||||
display_objs.append((mesh, item))
|
||||
if len(colors)>0:
|
||||
mesh = Mesh.create(faces= faces, vertices=verts, colors=colors)
|
||||
else:
|
||||
mesh = Mesh.create(faces= faces, vertices=verts)
|
||||
display_objs.append((mesh, item))
|
||||
|
||||
elif item is not None:
|
||||
display_objs.append((item, item))
|
||||
@@ -225,6 +222,7 @@ def assign_color(obj_display, props) -> None:
|
||||
|
||||
# initialize Speckle Blue color
|
||||
color = DEFAULT_COLOR
|
||||
opacity = None
|
||||
|
||||
try:
|
||||
# prioritize renderMaterials for Meshes & Brep
|
||||
@@ -232,8 +230,10 @@ def assign_color(obj_display, props) -> None:
|
||||
# print(obj_display.get_member_names())
|
||||
if hasattr(obj_display, 'renderMaterial'):
|
||||
color = obj_display['renderMaterial']['diffuse']
|
||||
opacity = obj_display['renderMaterial']['opacity']
|
||||
elif hasattr(obj_display, '@renderMaterial'):
|
||||
color = obj_display['@renderMaterial']['diffuse']
|
||||
opacity = obj_display['@renderMaterial']['opacity']
|
||||
|
||||
elif isinstance(obj_display, Mesh) and isinstance(obj_display.colors, List) and len(obj_display.colors)>1:
|
||||
sameColors = True
|
||||
@@ -256,26 +256,35 @@ def assign_color(obj_display, props) -> None:
|
||||
color = obj_display['@displayStyle']['color']
|
||||
elif hasattr(obj_display, 'renderMaterial'):
|
||||
color = obj_display['renderMaterial']['diffuse']
|
||||
opacity = obj_display['renderMaterial']['opacity']
|
||||
elif hasattr(obj_display, '@renderMaterial'):
|
||||
color = obj_display['@renderMaterial']['diffuse']
|
||||
opacity = obj_display['@renderMaterial']['opacity']
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
r, g, b = get_r_g_b(color)
|
||||
hex_color = '#%02x%02x%02x' % (r, g, b)
|
||||
props['color'] = hex_color
|
||||
a, r, g, b = get_r_g_b(color)
|
||||
if opacity is not None and isinstance(opacity, float):
|
||||
a_test = int(255* opacity)
|
||||
if 0 <= a_test <= 255:
|
||||
a = a_test
|
||||
# hex_color = '#%02x%02x%02x' % (r, g, b)
|
||||
props['color'] = f'rgba({r},{g},{b},{a})'
|
||||
|
||||
def get_r_g_b(rgb: int) -> Tuple[int, int, int]:
|
||||
"""Get R, G, B values from int."""
|
||||
|
||||
r = g = b = 0
|
||||
a = 255
|
||||
try:
|
||||
a = (rgb & 0xFF000000) >> 24
|
||||
r = (rgb & 0xFF0000) >> 16
|
||||
g = (rgb & 0xFF00) >> 8
|
||||
b = rgb & 0xFF
|
||||
except Exception as e:
|
||||
r = g = b = 150
|
||||
return r, g, b
|
||||
a = 255
|
||||
return a, r, g, b
|
||||
|
||||
def assign_display_properties(feature: Dict, f_base: "Base", obj_display: "Base") -> None:
|
||||
"""Assign displayProperties to the feature."""
|
||||
|
||||
@@ -1,5 +1,69 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<style>
|
||||
|
||||
.switch {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
right: 1vw;
|
||||
top: 10px;
|
||||
width: 70px;
|
||||
height: 23px;
|
||||
z-index: 1000000;
|
||||
}
|
||||
|
||||
.switch span {
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
}
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(17px);
|
||||
-ms-transform: translateX(17px);
|
||||
transform: translateX(17px);
|
||||
}
|
||||
|
||||
</style>
|
||||
<head>
|
||||
<meta charset="{{ config['server']['encoding'] }}">
|
||||
<title>{% block title %}{% endblock %}{% if not self.title() %}{{ config['metadata']['identification']['title'] }}{% endif %}</title>
|
||||
|
||||
@@ -5,15 +5,37 @@
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css"/>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css"/>
|
||||
<script src="https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster-src.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
|
||||
<script src="https://cdn.maptiler.com/maptiler-sdk-js/v2.2.2/maptiler-sdk.umd.js"></script>
|
||||
<link href="https://cdn.maptiler.com/maptiler-sdk-js/v2.2.2/maptiler-sdk.css" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
|
||||
{% block body_map %}
|
||||
|
||||
|
||||
<div class="row">
|
||||
{% if not data['missing_url'] %}
|
||||
<div id="items-map" style="min-height: 80vh;"></div>
|
||||
|
||||
<div class="form-group" >
|
||||
<label class="switch">3D
|
||||
<input id="modeSwitch" type="checkbox">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div id="map2d" style="height: 80vh;"></div>
|
||||
<div id="map3d" style="height: 0vh;"></div>
|
||||
{% else %}
|
||||
<div id="items-map" style="min-height: 40vh;"></div>
|
||||
|
||||
<div class="form-group" >
|
||||
<label class="switch">3D
|
||||
<input id="modeSwitch" type="checkbox" disabled="true">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div id="map2d" style="height: 40vh;"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -290,7 +312,12 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<p>
|
||||
4. Speckle project comments: <a href = "https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments">https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments</a>
|
||||
4. Rhino detailed building: <a href = "https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/9c43d7569c&limit=100000&northDegrees=-117">https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/9c43d7569c&limit=100000&northDegrees=-117</a>
|
||||
</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<p>
|
||||
5. Speckle project comments: <a href = "https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments">https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments</a>
|
||||
</p>
|
||||
</tr>
|
||||
|
||||
@@ -314,64 +341,204 @@
|
||||
{% block extrafoot %}
|
||||
|
||||
<script>
|
||||
var map = L.map('items-map').setView([45, 0], 2);
|
||||
map.addLayer(new L.TileLayer(
|
||||
'{{ config['server']['map']['url'] }}', {
|
||||
maxZoom: 22,
|
||||
attribution: '{{ config['server']['map']['attribution'] | safe }} © Data: <a href="https://speckle.systems/">Speckle Systems</a>'
|
||||
// attach even to modeSwitch btn
|
||||
document.getElementById("modeSwitch").onclick = switchMode;
|
||||
var el = document.getElementById("modeSwitch");
|
||||
if (el.addEventListener)
|
||||
el.addEventListener("click", switchMode, false);
|
||||
else if (el.attachEvent)
|
||||
el.attachEvent('onclick', switchMode);
|
||||
|
||||
function switchMode() {
|
||||
btn = document.getElementById('modeSwitch');
|
||||
if (btn.checked){
|
||||
document.getElementById('map2d').style.height = '0vh';
|
||||
document.getElementById('map3d').style.height = '80vh';
|
||||
}
|
||||
));
|
||||
|
||||
var geojson_data = {{ data['features'] | to_json | safe }};
|
||||
// var geojson_comments = {{ data['comments'] | to_json | safe }};
|
||||
|
||||
var items = new L.GeoJSON(geojson_data, {
|
||||
filter: (feature) => {
|
||||
return feature.displayProperties["object_type"] == "geometry"
|
||||
},
|
||||
pointToLayer: (feature, latlng) => {
|
||||
return new L.circleMarker(latlng)
|
||||
},
|
||||
onEachFeature: function (feature, layer) {
|
||||
var url = '{{ data['speckle_project_url'] }}/models/' + feature.id.split("_")[0]
|
||||
var html = '<span><td><p>' + feature['properties']['speckle_type'] + '</p></td><a href="' + url + '" target="_blank">' + feature['properties']['id'].split("_")[0] + '</a></span>';
|
||||
layer.bindPopup(html);
|
||||
|
||||
var myFillColor = feature.displayProperties['color'];
|
||||
var mylineWeight = feature.displayProperties['lineWidth'];
|
||||
var myRadius = feature.displayProperties['radius'];
|
||||
|
||||
layer.setStyle({
|
||||
fillColor: myFillColor,
|
||||
color: myFillColor,
|
||||
fillOpacity: 0.8,
|
||||
weight: mylineWeight,
|
||||
radius: myRadius
|
||||
});
|
||||
else {
|
||||
document.getElementById('map2d').style.height = '80vh';
|
||||
document.getElementById('map3d').style.height = '0vh';
|
||||
}
|
||||
}); //.addTo(map);
|
||||
|
||||
var comments = new L.GeoJSON(geojson_data, {
|
||||
filter: (feature) => {
|
||||
return feature.displayProperties["object_type"] == "comment"
|
||||
},
|
||||
pointToLayer: (feature, latlng) => {
|
||||
return new L.marker(latlng)
|
||||
},
|
||||
onEachFeature: function (feature, layer) {
|
||||
var url = '{{ data['speckle_project_url'] }}/models/' + feature.properties.resource_id + '#threadId=' + feature.id;
|
||||
var html = '<span><td><a href="' + url + '" target="_blank">Go to thread</a></td> <td><p>' + feature['properties']['text_html'] + '</p></td> </span>';
|
||||
layer.bindPopup(html);
|
||||
}
|
||||
}); //.addTo(map);
|
||||
}
|
||||
|
||||
var group = L.featureGroup([items, comments])
|
||||
.addTo(map);
|
||||
|
||||
//map.addLayer(lines);
|
||||
var data = {{ data | to_json | safe }};
|
||||
var geojson_data = {{ data['features'] | to_json | safe }};
|
||||
|
||||
map.fitBounds(group.getBounds());
|
||||
// map.setZoom(19); // in order for the tiles to load
|
||||
// Leaflet 2d map
|
||||
function initialize2d() {
|
||||
var map = L.map('map2d').setView([45, 0], 2);
|
||||
map.addLayer(new L.TileLayer(
|
||||
'{{ config['server']['map']['url'] }}', {
|
||||
maxZoom: 22,
|
||||
attribution: '{{ config['server']['map']['attribution'] | safe }} © Data: <a href="https://speckle.systems/">Speckle Systems</a>'
|
||||
}
|
||||
));
|
||||
|
||||
var items = new L.GeoJSON(geojson_data, {
|
||||
filter: (feature) => {
|
||||
return feature.displayProperties["object_type"] == "geometry"
|
||||
},
|
||||
pointToLayer: (feature, latlng) => {
|
||||
return new L.circleMarker(latlng)
|
||||
},
|
||||
onEachFeature: function (feature, layer) {
|
||||
var url = '{{ data['speckle_project_url'] }}/models/' + feature.id.split("_")[0]
|
||||
var html = '<span><td><p>' + feature['properties']['speckle_type'] + '</p></td><a href="' + url + '" target="_blank">' + feature['properties']['id'].split("_")[0] + '</a></span>';
|
||||
layer.bindPopup(html);
|
||||
|
||||
var myFillColor = feature.displayProperties['color'];
|
||||
var mylineWeight = feature.displayProperties['lineWidth'];
|
||||
var myRadius = feature.displayProperties['radius'];
|
||||
|
||||
layer.setStyle({
|
||||
fillColor: myFillColor,
|
||||
color: myFillColor,
|
||||
fillOpacity: 0.8,
|
||||
weight: mylineWeight,
|
||||
radius: myRadius
|
||||
});
|
||||
}
|
||||
}); //.addTo(map);
|
||||
|
||||
var comments = new L.GeoJSON(geojson_data, {
|
||||
filter: (feature) => {
|
||||
return feature.displayProperties["object_type"] == "comment"
|
||||
},
|
||||
pointToLayer: (feature, latlng) => {
|
||||
return new L.marker(latlng)
|
||||
},
|
||||
onEachFeature: function (feature, layer) {
|
||||
var url = '{{ data['speckle_project_url'] }}/models/' + feature.properties.resource_id + '#threadId=' + feature.id;
|
||||
var html = '<span><td><a href="' + url + '" target="_blank">Go to thread</a></td> <td><p>' + feature['properties']['text_html'] + '</p></td> </span>';
|
||||
layer.bindPopup(html);
|
||||
}
|
||||
}); //.addTo(map);
|
||||
|
||||
var group = L.featureGroup([items, comments])
|
||||
.addTo(map);
|
||||
|
||||
//map.addLayer(lines);
|
||||
|
||||
map.fitBounds(group.getBounds());
|
||||
// map.setZoom(19); // in order for the tiles to load
|
||||
};
|
||||
|
||||
|
||||
// MapTiler 3d map
|
||||
function hexToRgb(hex) {
|
||||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16), parseInt(result[0], 16)] : null;
|
||||
};
|
||||
function rgbaToArgbList(color) {
|
||||
col = color.replace('rgba(','').replace(')','').split(',',4);
|
||||
value = [ parseInt(col[0]), parseInt(col[1]), parseInt(col[2]), parseInt(col[3]) ];
|
||||
return value;
|
||||
}
|
||||
function rgbaToArgbListDarker(color) {
|
||||
col = color.replace('rgba(','').replace(')','').split(',',4);
|
||||
value = [ parseInt(col[0])*0.95, parseInt(col[1])*0.95, parseInt(col[2])*0.95, parseInt(col[3]) ];
|
||||
return value;
|
||||
}
|
||||
|
||||
function initialize3d() {
|
||||
maptilersdk.config.apiKey = '{{ config["server"]["map"]["key"] }}';
|
||||
speckle_data = JSON.parse(JSON.stringify(data))
|
||||
|
||||
var speckle_features = []
|
||||
for (let i = 0; i < speckle_data.features.length; i++) {
|
||||
feature = speckle_data.features[i];
|
||||
coords = feature.geometry.coordinates;
|
||||
|
||||
if (feature.geometry.type.includes("Polygon")) {
|
||||
|
||||
// check orientation of each PolygonPart, if vertical - shift points slightly
|
||||
for (let p = 0; p < coords.length; p++) {
|
||||
for (let c = 0; c < coords[p].length; c++) {
|
||||
|
||||
sum_orientation = 0;
|
||||
polygon_pts = coords[p][c]; // usually 3 for Mesh faces
|
||||
for (let k = 0; k < polygon_pts.length; k++){
|
||||
index = k + 1
|
||||
if (k == polygon_pts.length - 1){index = 0}
|
||||
pt = polygon_pts[k]
|
||||
pt2 = polygon_pts[index]
|
||||
sum_orientation += (pt2[0] - pt[0]) * (pt2[1] + pt[1])
|
||||
};
|
||||
|
||||
createdPolygon = false;
|
||||
if (-0.01 < sum_orientation && sum_orientation <0.01){
|
||||
coords[p][c][0][0] += 0.0000001;
|
||||
coords[p][c][0][1] += 0.0000001;
|
||||
coords[p][c][1][0] -= 0.0000001;
|
||||
coords[p][c][1][1] -= 0.0000001;
|
||||
if(polygon_pts.length==3) {
|
||||
createdPolygon = true;
|
||||
|
||||
multipolygon_coords = [coords[p][c]];
|
||||
speckle_features.push({"id": speckle_features.length, "type":"Feature",
|
||||
"geometry": {"type": "MultiPolygon", "coordinates":[multipolygon_coords]},
|
||||
"properties": speckle_data.features[i].properties });
|
||||
|
||||
}
|
||||
else if (polygon_pts.length==4) {
|
||||
createdPolygon = true;
|
||||
|
||||
multipolygon_coords = [coords[p][c].slice(0,3)];
|
||||
speckle_features.push({"id": speckle_features.length, "type":"Feature",
|
||||
"geometry": {"type": "MultiPolygon", "coordinates":[multipolygon_coords]},
|
||||
"properties": speckle_data.features[i].properties });
|
||||
|
||||
multipolygon_coords = [[coords[p][c][2], coords[p][c][3], coords[p][c][0]]];
|
||||
speckle_features.push({"id": speckle_features.length, "type":"Feature", "geometry": {"type": "MultiPolygon", "coordinates":[multipolygon_coords]}, "properties": speckle_data.features[i].properties });
|
||||
};
|
||||
};
|
||||
if (createdPolygon == false){
|
||||
multipolygon_coords = [coords[p][c]];
|
||||
speckle_features.push({"id": speckle_features.length, "type":"Feature",
|
||||
"geometry": {"type": "MultiPolygon", "coordinates":[multipolygon_coords]},
|
||||
"properties": speckle_data.features[i].properties });
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var extent = speckle_data["extent"];
|
||||
speckle_data.features = speckle_features;
|
||||
|
||||
// Create deck.gl map
|
||||
const deckgl = new deck.DeckGL({
|
||||
container: 'map3d',
|
||||
map: maptilersdk,
|
||||
mapStyle: maptilersdk.MapStyle.STREETS.PASTEL,
|
||||
initialViewState: {
|
||||
longitude: extent[0] + (extent[2]-extent[0])/2,
|
||||
latitude: extent[1] + (extent[3]-extent[1])/2,
|
||||
zoom: 22,
|
||||
pitch: 60,
|
||||
bearing: 1.469387755102039
|
||||
},
|
||||
controller: true,
|
||||
|
||||
layers: [
|
||||
new deck.GeoJsonLayer({
|
||||
id: 'speckle_data',
|
||||
data: speckle_data,
|
||||
// Styles
|
||||
filled: true,
|
||||
getFillColor: f => rgbaToArgbList(f.properties.color),
|
||||
getLineWidth: 0.05,
|
||||
getLineColor: f => rgbaToArgbListDarker(f.properties.color),
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
initialize2d();
|
||||
initialize3d();
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Leaflet demo</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css"/>
|
||||
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<main style="margin-left: 20px;margin-right: 20px;">
|
||||
|
||||
<div class="row">
|
||||
<h3>Speckle pygeoapi demo: construct URL</h3>
|
||||
<div class="form-group" ><label style="min-width: 10vw;display:inline-block">Speckle Model URL: </label>
|
||||
<input value="https://app.speckle.systems/projects/64753f52b7/models/338b386787" id="speckle_model" type="text" maxlength="512" style="min-width: 55vw;" class="searchField"/></div>
|
||||
<div class="form-group"><label style="min-width: 10vw;display:inline-block">Data type: </label>
|
||||
<select id="data_type" style="min-width: 55vw;">
|
||||
<option value="polygons">polygons</option>
|
||||
<option value="points">points</option>
|
||||
<option value="lines">lines</option>
|
||||
<option value="projectcomments">projectcomments</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group"><label style="min-width: 10vw;display:inline-block">Preserve attributes: </label>
|
||||
<select id="preserve_attributes" style="min-width: 55vw;">
|
||||
<option value="false">false</option>
|
||||
<option value="true">true</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group"><label style="min-width: 10vw;display:inline-block">Feature limit: </label>
|
||||
<input value="100000" id="limit" type="text" maxlength="512" style="min-width: 55vw;" class="searchField"/></div>
|
||||
|
||||
<div class="form-group"><label style="min-width: 10vw;display:inline-block">Lat: </label>
|
||||
<input value="-0.031405" id="lat" type="text" maxlength="512" style="min-width: 55vw;" class="searchField"/></div>
|
||||
<div class="form-group"><label style="min-width: 10vw;display:inline-block">Lon: </label>
|
||||
<input value="109.335828" id="lon" type="text" maxlength="512" style="min-width: 55vw;" class="searchField"/></div>
|
||||
<div class="form-group"><label style="min-width: 10vw;display:inline-block">North (degrees): </label>
|
||||
<input value="" id="north_degrees" type="text" maxlength="512" style="min-width: 55vw;" class="searchField"/></div>
|
||||
|
||||
<div class="form-group"><label style="min-width: 10vw;display:inline-block">Final URL: </label>
|
||||
<input value="" id="link" type="text" maxlength="512" style="min-width: 55vw;" class="searchField"/></div>
|
||||
|
||||
<input id="clickMe" type="button" value="Refresh map" onclick="doFunction();" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="row"><p></p></div>
|
||||
<div class="row">
|
||||
<div id="items-map" style="min-height: 60vh;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
<script>
|
||||
// attach event to a button click
|
||||
document.getElementById("clickMe").onclick = doFunction;
|
||||
var el = document.getElementById("clickMe");
|
||||
if (el.addEventListener)
|
||||
el.addEventListener("click", doFunction, false);
|
||||
else if (el.attachEvent)
|
||||
el.attachEvent('onclick', doFunction);
|
||||
|
||||
// create map
|
||||
var map = L.map('items-map').setView([ 45 , -75 ], 5);
|
||||
map.addLayer(new L.TileLayer(
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 22,
|
||||
attribution: '© <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a> © Data: <a href="https://speckle.systems/">Speckle Systems</a>'
|
||||
}
|
||||
));
|
||||
|
||||
// load Speckle data
|
||||
document.getElementById('link').disabled=true;
|
||||
doFunction();
|
||||
|
||||
async function doFunction() {
|
||||
map.eachLayer(function (layer) {
|
||||
if (!(layer instanceof L.TileLayer)){
|
||||
map.removeLayer(layer);
|
||||
}
|
||||
});
|
||||
|
||||
// construnt data URL
|
||||
var link = "https://geo.speckle.systems/?speckleUrl=";
|
||||
if (document.getElementById("speckle_model").value!=""){
|
||||
link += document.getElementById("speckle_model").value.replace(" ", "")
|
||||
}
|
||||
if (document.getElementById("data_type").value!=""){
|
||||
link += "&datatype=" + document.getElementById("data_type").value.replace(" ", "")
|
||||
}
|
||||
if (document.getElementById("limit").value!=""){
|
||||
link += "&limit=" + document.getElementById("limit").value.replace(" ", "")
|
||||
}
|
||||
if (document.getElementById("preserve_attributes").value!=""){
|
||||
link += "&preserveAttributes=" + document.getElementById("preserve_attributes").value.replace(" ", "")
|
||||
}
|
||||
|
||||
|
||||
if (document.getElementById("lon").value!=""){
|
||||
link += "&lon=" + document.getElementById("lon").value.replace(" ", "")
|
||||
}
|
||||
if (document.getElementById("lat").value!=""){
|
||||
link += "&lat=" + document.getElementById("lat").value.replace(" ", "")
|
||||
}
|
||||
if (document.getElementById("north_degrees").value!=""){
|
||||
link += "&northDegrees=" + document.getElementById("north_degrees").value.replace(" ", "")
|
||||
}
|
||||
|
||||
// set URL value to the text field
|
||||
document.getElementById("link").value = link;
|
||||
|
||||
// get Speckle data
|
||||
const speckle_data = await fetch(link, {
|
||||
headers: {
|
||||
'Accept': 'application/geo+json'
|
||||
}
|
||||
}).then(response => response.json());
|
||||
|
||||
// add data to map
|
||||
speckle_layer = L.geoJSON(speckle_data, {
|
||||
filter: (feature) => {
|
||||
return feature.displayProperties["object_type"] == "comment"
|
||||
},
|
||||
pointToLayer: (feature, latlng) => {
|
||||
return new L.marker(latlng)
|
||||
},
|
||||
onEachFeature: function (feature, layer) {
|
||||
var html = '<span><td><p>' + feature['properties']['text_html'] + '</p></td> </span>';
|
||||
layer.bindPopup(html);
|
||||
}
|
||||
});
|
||||
speckle_layer.addTo(map);
|
||||
|
||||
speckle_layer2 = L.geoJSON(speckle_data, {
|
||||
filter: (feature) => {
|
||||
return feature.displayProperties["object_type"] == "geometry"
|
||||
},
|
||||
pointToLayer: (feature, latlng) => {
|
||||
return new L.circleMarker(latlng)
|
||||
},
|
||||
onEachFeature: function (feature, layer) {
|
||||
var html = '<span><td><p>' + feature['properties']['speckle_type'] + '</p></td></span>';
|
||||
layer.bindPopup(html);
|
||||
|
||||
var myFillColor = feature.displayProperties['color'];
|
||||
var mylineWeight = feature.displayProperties['lineWidth'];
|
||||
var myRadius = feature.displayProperties['radius'];
|
||||
|
||||
layer.setStyle({
|
||||
fillColor: myFillColor,
|
||||
color: myFillColor,
|
||||
fillOpacity: 0.8,
|
||||
weight: mylineWeight,
|
||||
radius: myRadius
|
||||
});
|
||||
}
|
||||
});
|
||||
speckle_layer2.addTo(map);
|
||||
|
||||
if (document.getElementById("data_type").value.replace(" ","").toLowerCase() == "projectcomments"){
|
||||
map.fitBounds(speckle_layer.getBounds())
|
||||
}else{
|
||||
map.fitBounds(speckle_layer2.getBounds())
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,287 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Maptalks demo</title>
|
||||
<style type="text/css">
|
||||
html,body{margin:0px;height:100%;width:100%}
|
||||
.container{width:100%;height:100%}
|
||||
</style>
|
||||
<link rel="stylesheet" href="https://unpkg.com/maptalks/dist/maptalks.css">
|
||||
<script type="text/javascript" src="https://unpkg.com/maptalks/dist/maptalks.min.js"></script>
|
||||
<body>
|
||||
|
||||
<div class="row">
|
||||
<h3>Speckle pygeoapi demo: display comments</h3>
|
||||
</div>
|
||||
<div id="map" class="container"></div>
|
||||
|
||||
<script>
|
||||
var map = new maptalks.Map('map', {
|
||||
center: [-0.113049, 51.498568],
|
||||
zoom: 14,
|
||||
pitch : 56,
|
||||
bearing : 60,
|
||||
baseLayer: new maptalks.TileLayer('base', {
|
||||
urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
|
||||
subdomains: ["a","b","c","d"],
|
||||
attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>'
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
(async () => {
|
||||
const speckle_data2 = await fetch('https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/37d93c5d32&preserveAttributes=true', {
|
||||
//const speckle_data = await fetch('http://localhost:5000/?speckleUrl=https://app.speckle.systems/projects/64753f52b7/models/338b386787&limit=1000000&lat=-0.031405&lon=109.335828&preserveAttributes=true', {
|
||||
headers: {
|
||||
'Accept': 'application/geo+json'
|
||||
}
|
||||
}).then(response => response.json());
|
||||
console.log(speckle_data2)
|
||||
|
||||
var speckle_features = []
|
||||
for (let i = 0; i < speckle_data2.features.length; i++) {
|
||||
feature = speckle_data2.features[i];
|
||||
coords = feature.geometry.coordinates;
|
||||
|
||||
if (feature.geometry.type.includes("Polygon")) {
|
||||
|
||||
// check orientation of each PolygonPart
|
||||
for (let c = 0; c < coords[0].length; c++) {
|
||||
|
||||
sum_orientation = 0;
|
||||
polygon_pts = coords[0][c]; // usually 3 for Mesh faces
|
||||
for (let k = 0; k < polygon_pts.length; k++){
|
||||
index = k + 1
|
||||
if (k == polygon_pts.length - 1){index = 0}
|
||||
pt = polygon_pts[k]
|
||||
pt2 = polygon_pts[index]
|
||||
sum_orientation += (pt2[0] - pt[0]) * (pt2[1] + pt[1])
|
||||
};
|
||||
if (sum_orientation <0.01 ){
|
||||
coords[0][c][0][0] += 0.000001;
|
||||
coords[0][c][0][1] += 0.000001;
|
||||
};
|
||||
};
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPolygon(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : 'rgb(200,200,200)',
|
||||
'lineOpacity' : 0.9,
|
||||
'lineWidth' : 1.5,
|
||||
'polygonFill' : feature.displayProperties.color,
|
||||
'polygonOpacity' : 1
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("MultiLineString")){
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiLineString(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : feature.displayProperties.color,
|
||||
'lineOpacity' : 1,
|
||||
'lineWidth' : 2
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("LineString")){
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.LineString(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : feature.displayProperties.color,
|
||||
'lineOpacity' : 1,
|
||||
'lineWidth' : 2
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("MultiPoint")){
|
||||
symbol= {
|
||||
'markerType': 'ellipse',
|
||||
'markerFill': speckle_data.features[i].displayProperties.color,
|
||||
'markerFillOpacity': 0.7,
|
||||
'markerLineColor': speckle_data.features[i].displayProperties.color,
|
||||
'markerLineWidth': 0,
|
||||
'markerLineOpacity': 1,
|
||||
'markerLineDasharray':[],
|
||||
'markerWidth': 10,
|
||||
'markerHeight': 10,
|
||||
'markerDx': -10,
|
||||
'markerDy': 0,
|
||||
'markerOpacity' : 1,
|
||||
'textFaceName' : 'sans-serif',
|
||||
'textName' : speckle_data.features[i].properties["FID"],
|
||||
'textFill' : '#34495e',
|
||||
'textHorizontalAlignment' : 'right',
|
||||
'textSize' : 20
|
||||
};
|
||||
if (feature.displayProperties["object_type"] == "comment"){
|
||||
var strippedHtml = feature.properties.text_html.replaceAll(' ', ' ').replaceAll('<br>', '\n').replace(/<[^>]+>/g, '');
|
||||
symbol.textName = strippedHtml;
|
||||
symbol.textSize = 10;
|
||||
};
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPoint(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
cursor : 'pointer',
|
||||
symbol: symbol
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
speckle_layer2 = new maptalks.VectorLayer('vector2', speckle_features, { enableAltitude : true
|
||||
, drawAltitude : {
|
||||
//polygonFill : '#1bbc9b',
|
||||
//polygonOpacity : 0.3,
|
||||
//lineWidth : 0
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
speckle_layer2.addTo(map);
|
||||
map.fitExtent(speckle_layer2.getExtent(), 0);
|
||||
|
||||
//map.fitBounds(speckle_layer.getBounds())
|
||||
|
||||
const speckle_data = await fetch('https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments', {
|
||||
//const speckle_data = await fetch('http://localhost:5000/?speckleUrl=https://app.speckle.systems/projects/64753f52b7/models/338b386787&limit=1000000&lat=-0.031405&lon=109.335828&preserveAttributes=true', {
|
||||
headers: {
|
||||
'Accept': 'application/geo+json'
|
||||
}
|
||||
}).then(response => response.json());
|
||||
console.log(speckle_data)
|
||||
|
||||
var speckle_features = []
|
||||
for (let i = 0; i < speckle_data.features.length; i++) {
|
||||
feature = speckle_data.features[i];
|
||||
coords = feature.geometry.coordinates;
|
||||
|
||||
if (feature.geometry.type.includes("Polygon")) {
|
||||
|
||||
// check orientation of each PolygonPart
|
||||
for (let c = 0; c < coords[0].length; c++) {
|
||||
|
||||
sum_orientation = 0;
|
||||
polygon_pts = coords[0][c]; // usually 3 for Mesh faces
|
||||
for (let k = 0; k < polygon_pts.length; k++){
|
||||
index = k + 1
|
||||
if (k == polygon_pts.length - 1){index = 0}
|
||||
pt = polygon_pts[k]
|
||||
pt2 = polygon_pts[index]
|
||||
sum_orientation += (pt2[0] - pt[0]) * (pt2[1] + pt[1])
|
||||
};
|
||||
if (sum_orientation <0.01 ){
|
||||
coords[0][c][0][0] += 0.000001;
|
||||
coords[0][c][0][1] += 0.000001;
|
||||
};
|
||||
};
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPolygon(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : 'rgb(200,200,200)',
|
||||
'lineOpacity' : 0.3,
|
||||
'lineWidth' : 0.5,
|
||||
'polygonFill' : feature.displayProperties.color,
|
||||
'polygonOpacity' : 1
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("MultiLineString")){
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiLineString(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : feature.displayProperties.color,
|
||||
'lineOpacity' : 1,
|
||||
'lineWidth' : 2
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("LineString")){
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.LineString(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : feature.displayProperties.color,
|
||||
'lineOpacity' : 1,
|
||||
'lineWidth' : 2
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("MultiPoint")){
|
||||
symbol= {
|
||||
'markerType': 'ellipse',
|
||||
'markerFill': speckle_data.features[i].displayProperties.color,
|
||||
'markerFillOpacity': 0.7,
|
||||
'markerLineColor': speckle_data.features[i].displayProperties.color,
|
||||
'markerLineWidth': 0,
|
||||
'markerLineOpacity': 1,
|
||||
'markerLineDasharray':[],
|
||||
'markerWidth': 10,
|
||||
'markerHeight': 10,
|
||||
'markerDx': -10,
|
||||
'markerDy': 0,
|
||||
'markerOpacity' : 1,
|
||||
'textFaceName' : 'sans-serif',
|
||||
'textName' : speckle_data.features[i].properties["FID"],
|
||||
'textFill' : '#34495e',
|
||||
'textHorizontalAlignment' : 'right',
|
||||
'textSize' : 20
|
||||
};
|
||||
if (feature.displayProperties["object_type"] == "comment"){
|
||||
var strippedHtml = feature.properties.text_html.replaceAll(' ', ' ').replaceAll('<br>', '\n').replace(/<[^>]+>/g, '');
|
||||
symbol.textName = strippedHtml;
|
||||
symbol.textSize = 10;
|
||||
};
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPoint(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
cursor : 'pointer',
|
||||
symbol: symbol
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
speckle_layer = new maptalks.VectorLayer('vector', speckle_features, { enableAltitude : true
|
||||
, drawAltitude : {
|
||||
//polygonFill : '#1bbc9b',
|
||||
//polygonOpacity : 0.3,
|
||||
//lineWidth : 0
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
speckle_layer.addTo(map);
|
||||
map.fitExtent(speckle_layer.getExtent(), 0);
|
||||
|
||||
//map.fitBounds(speckle_layer.getBounds())
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,223 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Maptalks demo</title>
|
||||
<style type="text/css">
|
||||
html,body{margin:0px;height:100%;width:100%}
|
||||
.container{width:100%;height:100%}
|
||||
</style>
|
||||
<link rel="stylesheet" href="https://unpkg.com/maptalks/dist/maptalks.css">
|
||||
<script type="text/javascript" src="https://unpkg.com/maptalks/dist/maptalks.min.js"></script>
|
||||
<body>
|
||||
|
||||
<div class="row">
|
||||
<h3>Speckle pygeoapi demo: display polygons</h3>
|
||||
</div>
|
||||
<div id="map" class="container"></div>
|
||||
|
||||
<script>
|
||||
var map = new maptalks.Map('map', {
|
||||
center: [-0.113049, 51.498568],
|
||||
zoom: 14,
|
||||
pitch : 56,
|
||||
bearing : 60,
|
||||
baseLayer: new maptalks.TileLayer('base', {
|
||||
urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
|
||||
subdomains: ["a","b","c","d"],
|
||||
attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>'
|
||||
})
|
||||
});
|
||||
|
||||
(async () => {
|
||||
//const speckle_data = await fetch('https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments', {
|
||||
//var speckle_url = 'http://localhost:5000/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/9c43d7569c&limit=1000000&datatype=polygons&preserveattributes=false';
|
||||
// https://app.speckle.systems/projects/5feae56049/models/01c4183677
|
||||
var speckle_url = 'http://localhost:5000/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/01c4183677&limit=1000000&datatype=polygons&preserveattributes=true';
|
||||
|
||||
//var speckle_url = 'https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/9c43d7569c&northDegrees=-30&preserveAttributes=true';
|
||||
const speckle_data = await fetch(speckle_url, {
|
||||
headers: {
|
||||
'Accept': 'application/geo+json'
|
||||
}
|
||||
}).then(response => response.json());
|
||||
|
||||
var speckle_features = []
|
||||
for (let i = 0; i < speckle_data.features.length; i++) {
|
||||
feature = speckle_data.features[i];
|
||||
coords = feature.geometry.coordinates;
|
||||
|
||||
if (feature.geometry.type.includes("Polygon")) {
|
||||
|
||||
// check orientation of each PolygonPart, if vertical - shift points slightly
|
||||
for (let p = 0; p < coords.length; p++) {
|
||||
for (let c = 0; c < coords[p].length; c++) {
|
||||
|
||||
// each polygon Part unpacked
|
||||
sum_orientation = 0;
|
||||
polygon_pts = coords[p][c]; // usually 3 for Mesh faces
|
||||
|
||||
for (let k = 0; k < polygon_pts.length; k++){
|
||||
index = k + 1
|
||||
if (k == polygon_pts.length - 1){index = 0}
|
||||
pt = polygon_pts[k]
|
||||
pt2 = polygon_pts[index]
|
||||
sum_orientation += (pt2[0] - pt[0]) * (pt2[1] + pt[1])
|
||||
};
|
||||
|
||||
createdPolygon = false;
|
||||
if (-0.01 < sum_orientation && sum_orientation <0.01){
|
||||
coords[p][c][0][0] += 0.0000001;
|
||||
coords[p][c][0][1] += 0.0000001;
|
||||
coords[p][c][1][0] -= 0.0000001;
|
||||
coords[p][c][1][1] -= 0.0000001;
|
||||
if(polygon_pts.length==3) {
|
||||
createdPolygon = true;
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPolygon([coords[p][c]], {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : 'rgb(200,200,200)',
|
||||
'lineOpacity' : 0.3,
|
||||
'lineWidth' : 0.5,
|
||||
'polygonFill' : feature.displayProperties.color,
|
||||
'polygonOpacity' : 1
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
else if (polygon_pts.length==4) {
|
||||
createdPolygon = true;
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPolygon([coords[p][c].slice(0,3)], {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : 'rgb(200,200,200)',
|
||||
'lineOpacity' : 0.3,
|
||||
'lineWidth' : 0.5,
|
||||
'polygonFill' : feature.displayProperties.color,
|
||||
'polygonOpacity' : 1
|
||||
}
|
||||
})
|
||||
);
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPolygon([[coords[p][c][2], coords[p][c][3], coords[p][c][0]]], {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : 'rgb(200,200,200)',
|
||||
'lineOpacity' : 0.3,
|
||||
'lineWidth' : 0.5,
|
||||
'polygonFill' : feature.displayProperties.color,
|
||||
'polygonOpacity' : 1
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
if (createdPolygon == false){
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPolygon([coords[0][c]], {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : 'rgb(200,200,200)',
|
||||
'lineOpacity' : 0.3,
|
||||
'lineWidth' : 0.5,
|
||||
'polygonFill' : feature.displayProperties.color,
|
||||
'polygonOpacity' : 1
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} else if (feature.geometry.type.includes("MultiLineString")){
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiLineString(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : feature.displayProperties.color,
|
||||
'lineOpacity' : 1,
|
||||
'lineWidth' : 2
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("LineString")){
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.LineString(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
symbol: {
|
||||
'lineColor' : feature.displayProperties.color,
|
||||
'lineOpacity' : 1,
|
||||
'lineWidth' : 2
|
||||
}
|
||||
})
|
||||
);
|
||||
} else if (feature.geometry.type.includes("MultiPoint")){
|
||||
symbol= {
|
||||
'markerType': 'ellipse',
|
||||
'markerFill': speckle_data.features[i].displayProperties.color,
|
||||
'markerFillOpacity': 0.7,
|
||||
'markerLineColor': speckle_data.features[i].displayProperties.color,
|
||||
'markerLineWidth': 0,
|
||||
'markerLineOpacity': 1,
|
||||
'markerLineDasharray':[],
|
||||
'markerWidth': 10,
|
||||
'markerHeight': 10,
|
||||
'markerDx': -10,
|
||||
'markerDy': 0,
|
||||
'markerOpacity' : 1,
|
||||
'textFaceName' : 'sans-serif',
|
||||
'textName' : speckle_data.features[i].properties["FID"],
|
||||
'textFill' : '#34495e',
|
||||
'textHorizontalAlignment' : 'right',
|
||||
'textSize' : 20
|
||||
};
|
||||
if (feature.displayProperties["object_type"] == "comment"){
|
||||
var strippedHtml = feature.properties.text_html.replaceAll(' ', ' ').replaceAll('<br>', '\n').replace(/<[^>]+>/g, '');
|
||||
symbol.textName = strippedHtml;
|
||||
symbol.textSize = 10;
|
||||
};
|
||||
|
||||
speckle_features.push(
|
||||
new maptalks.MultiPoint(coords, {
|
||||
visible : true,
|
||||
cursor : null,
|
||||
cursor : 'pointer',
|
||||
symbol: symbol
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
speckle_layer = new maptalks.VectorLayer('vector', speckle_features, { enableAltitude : true
|
||||
, drawAltitude : {
|
||||
//polygonFill : '#1bbc9b',
|
||||
//polygonOpacity : 0.3,
|
||||
//lineWidth : 0
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
speckle_layer.addTo(map);
|
||||
map.fitExtent(speckle_layer.getExtent(), 0);
|
||||
|
||||
//map.fitBounds(speckle_layer.getBounds())
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user