15 Commits

Author SHA1 Message Date
KatKatKateryna 22176c8b8f Merge branch 'dev' into polishing_more
flake8 / flake8_py3 (push) Has been cancelled
2024-09-05 14:31:05 +01:00
KatKatKateryna 60c41dc76f double-check for display vals 2024-09-05 14:29:01 +01:00
KatKatKateryna 2900046d14 Merge branch 'dev' into polishing_more 2024-09-04 23:51:50 +01:00
KatKatKateryna f35cf4122f html syntax 2024-09-04 23:41:20 +01:00
KatKatKateryna 3b7877a0bf leaflet controls to the right 2024-09-04 23:30:44 +01:00
KatKatKateryna ab9df29ae4 add bbox per feature 2024-09-04 23:06:08 +01:00
KatKatKateryna 22968f0749 URL exceptions handling 2024-09-04 22:49:14 +01:00
KatKatKateryna ee37ca89e2 avoid multiple loops 2024-09-04 16:08:47 +01:00
KatKatKateryna 4e867c86d8 ensure speckleURL argument 2024-09-04 16:04:45 +01:00
KatKatKateryna 6d425d4212 split polygons in leaflet 2024-09-04 15:11:19 +01:00
KatKatKateryna b2c4498419 fix multipolygons 2024-09-04 14:17:15 +01:00
KatKatKateryna 3d83276498 prioritize attributes by default, less geometry divisions 2024-09-04 13:52:15 +01:00
KatKatKateryna c83f87425a fix multipolygons in 3d 2024-09-04 13:51:41 +01:00
KatKatKateryna eb381bdd2f traverse for colors 2024-09-04 11:32:11 +01:00
KatKatKateryna 93e0cd5792 colors and materials 2024-09-04 04:19:51 +01:00
33 changed files with 140 additions and 482 deletions
+1 -1
View File
@@ -530,7 +530,7 @@ paths:
- hello-world
servers:
- description: pygeoapi provides an API to geospatial data
url: https://geo.speckle.systems
url: http://localhost:5000
tags:
- description: pygeoapi provides an API to geospatial data
externalDocs:
-3
View File
@@ -1,6 +1,3 @@
access_log
error_log*
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
-3
View File
@@ -1,3 +0,0 @@
geo.speckle.systems {
reverse_proxy localhost:8000
}
+1 -1
View File
@@ -81,7 +81,7 @@ Then you can add it to the base map (e.g. using Leaflet and OpenStreetMap basema
loadSpeckleData();
async function loadSpeckleData() => {
var speckle_model_url = 'https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=polygons';
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());
+1 -1
View File
@@ -128,4 +128,4 @@ resources:
hello-world:
type: process
processor:
name: HelloWorld
name: HelloWorld
+1 -1
View File
@@ -75,7 +75,7 @@ LOGGER = logging.getLogger(__name__)
#: Return headers for requests (e.g:X-Powered-By)
HEADERS = {
'Content-Type': 'application/json',
# 'X-Powered-By': f'pygeoapi {__version__}'
'X-Powered-By': f'pygeoapi {__version__}'
}
CHARSET = ['utf-8']
+1 -1
View File
@@ -309,7 +309,7 @@ def get_collection_items(
# clear data if no URL params
load_data = False
for item in request.params:
if item.lower() == 'speckleurl' and len(request.params[item])>40 and ('speckleurl=' + request.params[item]) in provider_def['data'].lower():
if item == 'speckleUrl' and len(request.params[item])>40 and ('speckleUrl=' + request.params[item]) in provider_def['data']:
load_data = True
break
if load_data is False:
+24 -81
View File
@@ -34,14 +34,10 @@ import os
from typing import Union
import click
from datetime import datetime, timezone
from flask import (Flask, Blueprint, make_response, request,
send_from_directory, Response, Request, stream_with_context)
from http import HTTPStatus
import json
from urllib.request import urlopen
from pygeoapi.api import API, APIRequest, apply_gzip
import pygeoapi.api.coverages as coverages_api
import pygeoapi.api.environmental_data_retrieval as edr_api
@@ -50,7 +46,6 @@ import pygeoapi.api.maps as maps_api
import pygeoapi.api.processes as processes_api
import pygeoapi.api.stac as stac_api
import pygeoapi.api.tiles as tiles_api
from pygeoapi.provider.speckle_utils.legal import COUNTRY_CODES
from pygeoapi.openapi import load_openapi_document
from pygeoapi.config import get_config
from pygeoapi.util import get_mimetype, get_api_rules, render_j2_template
@@ -173,62 +168,6 @@ def execute_from_flask(api_function, request: Request, *args,
return get_response((headers, status, content))
def handle_client(url_route: str):
# if called fromm the browser, Exceptions from this function will result in infinite load
agent = request.headers.get('User-Agent')
if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
ip_address = request.environ['REMOTE_ADDR']
else:
ip_address = request.environ['HTTP_X_FORWARDED_FOR']
if agent is not None and "(https://www.checklyhq.com)" not in agent:
print(f"_______________________{datetime.now().astimezone(timezone.utc)} _URL access")
print(f"_Agent {url_route}: {agent}")
print(f"_IP Address: {ip_address}")
print(f"_Request URL: {request.url}")
request.url += f"&userAgent={agent}"
# by Agent:
if agent is not None and ("YaBrowser/" in agent or "yandex" in agent.lower()):
raise ValueError("Your browser is not supported.")
# by IP:
try:
url = 'https://ipinfo.io/' + ip_address + '/json'
res = urlopen(url)
data = json.load(res)
if isinstance(data, dict) and isinstance(data["country"], str):
if data["country"].lower() in COUNTRY_CODES:
raise PermissionError("Review Speckle Terms and Conditions")
else:
print(f"Error validating client: DATA {data}")
except Exception as e:
print(f"Error validating client from start: {e}")
def generate():
collection_id = "speckle"
yield loading_screen().data
handle_client("/")
CONFIG = get_config(request=request)
api_ = API(CONFIG, OPENAPI)
try:
browser_response = execute_from_flask(itemtypes_api.get_collection_items,
request, collection_id,
skip_valid_check=True)
yield browser_response.data
except PermissionError as ex:
raise ex
except Exception as ex:
yield error_screen(ex).data
@BLUEPRINT.route('/')
def landing_page():
"""
@@ -236,24 +175,41 @@ def landing_page():
:returns: HTTP response
"""
collection_id = "speckle"
agent = request.headers.get('User-Agent')
# Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
# Mozilla/5.0 QGIS/32815/Windows 10 Version 2009
# ArcGIS Pro 3.3.0 (00000000000) - ArcGISPro
browser_agent = False
browser_list = ["Chrome", "Safari", "Firefox", "Edg/", "Trident/"]
print(agent)
if "YaBrowser/" in agent:
raise ValueError("Your browser is not supported.")
for br in browser_list:
if agent is not None and br in agent:
if br in agent:
browser_agent = True
break
# if requested from the browser, return this, otherwise ignore IF statement
if request.method == 'GET' and browser_agent: # list items
def generate():
yield loading_screen().data
try:
browser_response = execute_from_flask(itemtypes_api.get_collection_items,
request, collection_id,
skip_valid_check=True)
yield browser_response.data
except Exception as ex:
yield error_screen(ex).data
return Response(stream_with_context(generate()))
# for non-browsers
handle_client("/")
CONFIG = get_config(request=request)
api_ = API(CONFIG, OPENAPI)
return get_response(api_.landing_page(request))
def error_screen(ex: Exception):
@@ -338,20 +294,10 @@ def collections(collection_id=None):
:returns: HTTP response
"""
handle_client("/collections")
# raise NotImplementedError()
return get_response(api_.describe_collections(request, collection_id))
@BLUEPRINT.route('/speckle')
def speckle_collection():
handle_client("/speckle")
collection_id="speckle"
return collection_items(collection_id=collection_id)
@BLUEPRINT.route('/collections/<path:collection_id>/schema')
def collection_schema(collection_id):
"""
@@ -397,9 +343,6 @@ def collection_items(collection_id, item_id=None):
:returns: HTTP response
"""
handle_client(f"/collections/{collection_id}/items")
collection_id = 'speckle'
if item_id is None:
+8 -39
View File
@@ -119,19 +119,11 @@ class SpeckleProvider(BaseProvider):
self.speckle_url = self.url.lower().split("speckleurl=")[-1].split("&")[0].split("@")[0].split("?")[0]
self.speckle_data = None
self.project_name = ""
self.project_id = ""
self.model_name = ""
self.sourceApp = ""
self.crs = None
self.crs_dict = None
self.commit_gis = False
self.url_params = {"url_data_type":"", "url_preserve_attributes":"", "url_crs_authid":"", "url_lat":"","url_lon":"","url_north_degrees":"","url_limit":""}
self.times = {}
self.country_code = ""
self.requested_data_type: str = "polygons (default)" # points, lines, polygons, projectcomments
self.preserve_attributes: str = "true (default)"
self.lat: float = 48.76755913928929 #51.52486388756923
@@ -139,13 +131,11 @@ class SpeckleProvider(BaseProvider):
self.north_degrees: float = 0
self.crs_authid = ""
self.limit = 10000
self.user_agent = ""
self.missing_url = ""
self.limit_message = ""
self.extent = [-180,-90,180,90]
self.extent3d = [-180,-90,0,180,90,1000]
self.material_color_proxies = {}
@@ -348,8 +338,7 @@ class SpeckleProvider(BaseProvider):
def load_speckle_data(self: str) -> Dict:
"""Receive and process Speckle data, return geojson."""
from datetime import datetime, timezone
from pygeoapi.provider.speckle_utils.server_utils import get_stream_branch, get_client, get_comments, set_actions
from pygeoapi.provider.speckle_utils.server_utils import get_stream_branch, get_client, get_comments
from specklepy.objects.base import Base
from specklepy.logging.exceptions import SpeckleException
@@ -371,10 +360,6 @@ class SpeckleProvider(BaseProvider):
# get stream and branch data
client = get_client(wrapper, url_proj)
stream, branch = get_stream_branch(self, client, wrapper)
if stream is None:
raise ValueError(f"Project from URL '{url_proj}' not found")
if branch is None:
raise ValueError(f"Model '{wrapper.model_id}' of the project '{stream['name']}' not found")
if self.requested_data_type == "projectcomments":
comments = get_comments(client, wrapper.stream_id, wrapper.model_id)
@@ -383,20 +368,16 @@ class SpeckleProvider(BaseProvider):
comments = {}
# set the Model name
self.project_id = wrapper.stream_id
self.project_name = stream['name']
self.model_name = branch['name']
commit = branch["commits"]["items"][0]
objId = commit["referencedObject"]
self.sourceApp = commit["sourceApplication"]
transport = ServerTransport(client=client, account=client.account, stream_id=wrapper.stream_id)
if transport == None:
raise SpeckleException("Transport not found")
# receive commit
set_actions(self, client)
try:
commit_obj = operations.receive(objId, transport, None)
except Exception as ex:
@@ -410,21 +391,18 @@ class SpeckleProvider(BaseProvider):
message="Received commit in pygeoapi",
)
print(f"_{datetime.now().astimezone(timezone.utc)} _Rendering model '{branch['name']}' of the project '{stream['name']}'")
print(f"Rendering model '{branch['name']}' of the project '{stream['name']}'")
speckle_data = self.traverse_data(commit_obj, comments)
set_actions(self, client, "GEO post-receive")
speckle_data["features"].extend(speckle_data["comments"])
speckle_data["comments"] = []
speckle_data["project_id"] = wrapper.stream_id
speckle_data["project"] = stream['name']
speckle_data["model"] = branch['name']
speckle_data["model_last_version_date"] = datetime.strptime(commit['createdAt'].replace("T", " ").replace("Z","").split(".")[0], '%Y-%m-%d %H:%M:%S')
speckle_data["model_id"] = wrapper.model_id
speckle_data["extent"] = self.extent
speckle_data["extent3d"] = self.extent3d
speckle_data["limit_message"] = self.limit_message
return speckle_data
@@ -442,7 +420,7 @@ class SpeckleProvider(BaseProvider):
)
from pygeoapi.provider.speckle_utils.crs_utils import get_set_crs_settings
from pygeoapi.provider.speckle_utils.feature_utils import create_features
from pygeoapi.provider.speckle_utils.display_utils import isDisplayable, set_default_color, get_material_color_proxies
from pygeoapi.provider.speckle_utils.display_utils import set_default_color, get_material_color_proxies
supported_classes = [GisFeature, GisPolygonElement, Mesh, Brep, Point, Line, Polyline, Curve, Arc, Circle, Ellipse, Polycurve]
supported_types = [y().speckle_type for y in supported_classes]
@@ -464,22 +442,16 @@ class SpeckleProvider(BaseProvider):
"extent": [-180,-90,180,90],
"model_crs": "-",
}
# rule to keep traversing the object's "x" attribute "item" (both conditions need to be fulfilled)
# 1. if the item type is not in supported (convertible) types or is GIS VectorLayer
# 2. if the item's value is a list or a GH object
rule = TraversalRule(
[lambda _: True],
lambda x: [
item
for item in x.get_member_names()
if (x.speckle_type.split(":")[-1] not in supported_types or isinstance(x, VectorLayer))
and (isinstance(getattr(x, item, None), list) or (self.sourceApp is not None and "grasshopper" in self.sourceApp.lower() and x.speckle_type == "Base") )
if isinstance(getattr(x, item, None), list)
and (x.speckle_type.split(":")[-1] not in supported_types or isinstance(x, VectorLayer))
],
)
# for the context list, save the displayable objects and Layers (for getting CRS for now)
context_list = [x for x in GraphTraversal([rule]).traverse(commit_obj) if isDisplayable(x.current) or x.current.speckle_type.endswith("VectorLayer")]
context_list = [x for x in GraphTraversal([rule]).traverse(commit_obj)]
get_set_crs_settings(self, commit_obj, context_list, data)
@@ -501,10 +473,7 @@ class SpeckleProvider(BaseProvider):
sorted_list[i]["properties"]["FID"] = i+1
data['features'] = sorted_list
time2 = datetime.now()
time_operation = (time2-time1).total_seconds()
self.times["time_sort"] = time_operation
# print(f"Sorting time: {time_operation}")
print(f"Sorting time: {(time2-time1).total_seconds()}")
return data
@@ -296,24 +296,8 @@ def assign_geometry(self: "SpeckleProvider", feature: Dict, f_base) -> Tuple[ Li
geometry["type"] = "MultiPolygon"
coord_counts.append(None)
polygon_3d = False
for mesh in f_base["displayValue"]:
for i, coord in enumerate(mesh.vertices):
if i>60:
break
if i%3 !=0:
continue
elif coord != 0:
polygon_3d = True
break
if polygon_3d is False:
for geom in f_base["geometry"]:
convert_polygon(geom, coords, coord_counts)
else:
for geom in f_base["displayValue"]:
convert_mesh_or_brep(geom, coords, coord_counts)
for geom in f_base["geometry"]:
convert_polygon(geom, coords, coord_counts)
elif self.requested_data_type == "points":
@@ -2,7 +2,6 @@
import copy
import math
from typing import List
from pygeoapi.provider.speckle_utils.legal import COUNTRY_CODES, STATES, POSTCODES
def reproject_bulk(self, all_coords: List[List[List[float]]], all_coord_counts: List[List[None| List[int]]], geometries) -> None:
@@ -14,12 +13,7 @@ def reproject_bulk(self, all_coords: List[List[List[float]]], all_coord_counts:
time1 = datetime.now()
flat_coords = reproject_2d_coords_list(self, all_coords)
time2 = datetime.now()
time_operation = (time2-time1).total_seconds()
self.times["time_reproject"] = time_operation
validate_coords(self, flat_coords[0])
if len(flat_coords)>2:
validate_coords(self, flat_coords[len(flat_coords)-1])
print(f"Reproject time: {(time2-time1).total_seconds()}")
# define type of features
feat_coord_group_is_multi = [True if None in x else False for x in all_coord_counts]
@@ -55,15 +49,7 @@ def reproject_bulk(self, all_coords: List[List[List[float]]], all_coord_counts:
if geometry["type"] == "MultiPoint":
poly_part.extend([local_flat_coords[ind] for ind in range_coords_indices])
else:
new_list = []
for ind in range_coords_indices:
try:
new_list.append(local_flat_coords[ind])
except Exception as e: # corrupted geometry, ignore altogether
new_list = []
break
if len(new_list)>0:
poly_part.append(new_list)
poly_part.append([local_flat_coords[ind] for ind in range_coords_indices])
start_index += part_count
@@ -75,10 +61,7 @@ def reproject_bulk(self, all_coords: List[List[List[float]]], all_coord_counts:
geometry["coordinates"].extend(polygon_parts)
time3 = datetime.now()
time_operation = (time3-time2).total_seconds()
self.times["time_reconstruct_geometry"] = time_operation
# print(f"Construct back geometry time: {time_operation}")
print(f"Construct back geometry time: {(time3-time2).total_seconds()}")
def reproject_2d_coords_list(self, coords_in: List[List[float]]) -> List[List[float]]:
"""Return coordinates in a CRS of SpeckleProvider."""
@@ -97,9 +80,7 @@ def reproject_2d_coords_list(self, coords_in: List[List[float]]) -> List[List[fl
all_x = [x[0] for x in transformed]
all_y = [x[1] for x in transformed]
all_z = [x[2] for x in transformed]
self.extent = [min(all_x), min(all_y), max(all_x), max(all_y)]
self.extent3d = [min(all_x), min(all_y), min(all_z), max(all_x), max(all_y), max(all_z)]
return transformed
def offset_rotate(self, coords_in: List[list]) -> List[List[float]]:
@@ -125,25 +106,3 @@ def offset_rotate(self, coords_in: List[list]) -> List[List[float]]:
)
return final_coords
def validate_coords(self, coords):
from geopy.geocoders import Nominatim
country_code = ""
state = ""
postcode = ""
try:
geolocator = Nominatim(user_agent="specklePygeoapi")
coord = f"{coords[1]}, {coords[0]}"
location = geolocator.reverse(coord, exactly_one=True)
if location is not None:
address = location.raw['address']
country_code = address.get('country_code', '')
state = address.get('state', '')
postcode = address.get('postcode', '')
except Exception as e:
print(f"Error validating project location: {e}")
self.country_code = country_code
if country_code in COUNTRY_CODES or state in STATES or postcode in POSTCODES:
print(f"Validating project location: blocked LAT LON {coords[1]}, {coords[0]}, {country_code}, {state}, {postcode}")
raise PermissionError("Review Speckle Terms and Conditions")
+1 -2
View File
@@ -51,7 +51,7 @@ def get_set_crs_settings(self: "SpeckleProvider", commit_obj: "Base", context_li
root_objects = []
try:
root_objects = [commit_obj] + commit_obj.elements + [c.current for c in context_list]
root_objects = [commit_obj] + commit_obj.elements
except AttributeError as ex:
pass # old commit structure
@@ -73,7 +73,6 @@ def get_set_crs_settings(self: "SpeckleProvider", commit_obj: "Base", context_li
offset_y = crs["offset_y"]
self.north_degrees = crs["rotation"]
create_crs_from_wkt(self, crs["wkt"])
self.commit_gis = True
if self.crs.to_authority() is not None:
data["model_crs"] = f"{self.crs.to_authority()}, {self.crs.name} "
+42 -134
View File
@@ -54,7 +54,6 @@ def separate_display_vals(displayValue: List) -> List[Tuple["Base"]]:
count = 0
all_count = len(item.faces)
sub_meshes = []
for _ in item.faces:
if count < all_count:
faces = []
@@ -62,67 +61,33 @@ def separate_display_vals(displayValue: List) -> List[Tuple["Base"]]:
colors = []
vert_num = item.faces[count]
if vert_num == 0:
vert_num = 3
elif vert_num == 1:
vert_num = 4
faces.append(vert_num)
faces.extend([ x for x in list(range(vert_num))])
try:
for ind in range(vert_num):
face_vert_index = count+1+ind
#print(face_vert_index)
vert_index = item.faces[face_vert_index]
for ind in range(vert_num):
face_vert_index = count+1+ind
vert_index = item.faces[face_vert_index]
new_vert = item.vertices[3*vert_index : 3*vert_index + 3]
verts.extend(new_vert)
new_vert = item.vertices[3*vert_index : 3*vert_index + 3]
verts.extend(new_vert)
if isinstance(item.colors, List) and len(item.colors) > vert_index:
color = item.colors[vert_index]
colors.append(color)
count += vert_num+1
if len(colors)>0:
mesh = Mesh.create(faces= faces, vertices=verts, colors=colors)
else:
mesh = Mesh.create(faces= faces, vertices=verts)
sub_meshes.append((mesh, item))
if isinstance(item.colors, List) and len(item.colors) > vert_index:
color = item.colors[vert_index]
colors.append(color)
except IndexError: # corrupted mesh, drop altogether
sub_meshes = []
break
display_objs.extend(sub_meshes)
count += vert_num+1
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))
return display_objs
def isDisplayable(obj: "Base") -> bool:
if is_primitive(obj):
return True
if obj.speckle_type.endswith("Feature"):
return True
displayValue = None
if hasattr(obj, 'displayValue'):
displayValue = getattr(obj, 'displayValue')
elif hasattr(obj, '@displayValue'):
displayValue = getattr(obj, '@displayValue')
# merge to sigle object, if List
if isinstance(displayValue, List):
return True
return False
def find_display_obj(obj) -> Tuple["Base", "Base"]:
"""Get displayable object."""
@@ -156,12 +121,11 @@ def find_display_obj(obj) -> Tuple["Base", "Base"]:
def is_convertible(obj) -> bool:
"""Check if the object can be converted directly."""
from specklepy.objects.geometry import Base, Point, Line, Polyline, Arc, Circle, Curve, Polycurve, Mesh, Brep
from specklepy.objects.geometry import Base, Point, Line, Arc, Circle, Curve, Polycurve, Mesh, Brep
if ( (isinstance(obj, Base) and obj.speckle_type.endswith("Feature")) or
isinstance(obj, Point) or
isinstance(obj, Line) or
isinstance(obj, Polyline) or
isinstance(obj, Arc) or
isinstance(obj, Circle) or
isinstance(obj, Curve) or
@@ -171,23 +135,6 @@ def is_convertible(obj) -> bool:
return True
return False
def is_primitive(obj) -> bool:
"""Check if the object can be converted directly."""
from specklepy.objects.geometry import Polyline, Point, Line, Arc, Circle, Curve, Polycurve, Mesh, Brep
if (
isinstance(obj, Point) or
isinstance(obj, Line) or
isinstance(obj, Polyline) or
isinstance(obj, Arc) or
isinstance(obj, Circle) or
isinstance(obj, Curve) or
isinstance(obj, Mesh)
):
return True
return False
def get_single_display_object(displayValForColor: List) -> "Base":
"""Get a merged Mesh or a first item from displayValue list."""
@@ -309,8 +256,8 @@ def set_default_color(context_list: List["TraversalContext"]) -> None:
for item in context_list:
# for GIS-commits, use default blue color
if isinstance(item.current, VectorLayer) or (item.parent is not None and isinstance(item.parent.current, VectorLayer)):
DEFAULT_COLOR = (255 << 24) + (10 << 16) + (132 << 8) + 255 # speckle blue, speckle_blue
if isinstance(item.current, VectorLayer):
DEFAULT_COLOR = (255 << 24) + (10 << 16) + (132 << 8) + 255
break
def getAllParents(tc: "TraversalContext"):
@@ -334,6 +281,22 @@ def assign_color(self: "SpeckleProvider", obj_display_tc: "TraversalContext", pr
from specklepy.objects.geometry import Mesh, Brep
for tc in getAllParents(obj_display_tc):
try:
color = self.material_color_proxies[tc.current.applicationId]
props['color'] = color
return
except:
pass
try:
color = self.material_color_proxies[obj_display.applicationId]
props['color'] = color
return
except:
pass
# initialize Speckle Blue color
color = DEFAULT_COLOR
opacity = None
@@ -341,62 +304,25 @@ def assign_color(self: "SpeckleProvider", obj_display_tc: "TraversalContext", pr
obj_display = obj_display_tc.current
try:
# first, choose if get color from the parent obj or displayValue
if hasattr(obj_display, 'displayStyle') or hasattr(obj_display, '@displayStyle') or hasattr(obj_display, 'renderMaterial') or hasattr(obj_display, '@renderMaterial'):
obj_display = obj_display_tc.current
else:
# this option will be not very reliable:
# there could be different colors for diff displayValues in the list
if hasattr(obj_display, 'displayValue'):
try:
displayVal = obj_display['displayValue']
except:
displayVal = obj_display.displayValue
if isinstance(displayVal, list) and len(displayVal)>0:
obj_display = displayVal[0]
elif hasattr(obj_display, '@displayValue') and isinstance(obj_display['@displayValue'], list) and len(obj_display['@displayValue'])>0:
obj_display = obj_display['@displayValue'][0]
# prioritize renderMaterials for Meshes & Brep
if isinstance(obj_display, Mesh) or isinstance(obj_display, Brep):
# print(obj_display.get_member_names())
if hasattr(obj_display, 'renderMaterial'):
try:
renderMaterial = obj_display['renderMaterial']
except:
renderMaterial = obj_display.renderMaterial
color = renderMaterial['diffuse']
opacity = renderMaterial['opacity']
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:
colors_number = 0
all_colors = []
sameColors = True
color1 = obj_display.colors[0]
for c in obj_display.colors:
if c not in all_colors:
colors_number += 1
all_colors.append(c)
if colors_number>1:
all_a = 0
all_r = 0
all_g = 0
all_b = 0
for col in all_colors:
a, r, g, b = get_r_g_b(col)
all_a += a
all_r += r
all_g += g
all_b += b
color = (
(int(all_a/len(obj_display.colors)) << 24) + (int(all_r/len(obj_display.colors)) << 16)
+ (int(all_g/len(obj_display.colors)) << 8) + int(all_b/len(obj_display.colors))
)
else:
color = obj_display.colors[0]
if c != color1:
sameColors = False
break
if sameColors is True:
color = color1
elif hasattr(obj_display, 'displayStyle'):
color = obj_display['displayStyle']['color']
@@ -424,24 +350,6 @@ def assign_color(self: "SpeckleProvider", obj_display_tc: "TraversalContext", pr
# hex_color = '#%02x%02x%02x' % (r, g, b)
props['color'] = f'rgba({r},{g},{b},{a})'
# if still not found, check proxies:
if color == DEFAULT_COLOR:
for tc in getAllParents(obj_display_tc):
try:
color = self.material_color_proxies[tc.current.applicationId]
props['color'] = color
return
except:
pass
try:
color = self.material_color_proxies[obj_display.applicationId]
props['color'] = color
return
except:
pass
def get_r_g_b(rgb: int) -> Tuple[int, int, int]:
"""Get R, G, B values from int."""
@@ -13,7 +13,7 @@ def initialize_features(self: "SpeckleProvider", all_coords, all_coord_counts, d
from specklepy.objects.graph_traversal.traversal import TraversalContext
from specklepy.objects.other import Collection
# print(f"Creating features..")
print(f"Creating features..")
time1 = datetime.now()
all_props = []
@@ -79,14 +79,14 @@ def initialize_features(self: "SpeckleProvider", all_coords, all_coord_counts, d
obj_get_color_tc = TraversalContext(obj_get_color, "", item)
assign_display_properties(self, feature, f_base, obj_get_color_tc)
assign_display_properties(self, feature, f_base, obj_get_color_tc)
feature["max_height"] = max([c[2] for c in coords])
feature["bbox"] = get_feature_bbox(coords)
data["features"].append(feature)
feature_count += 1
else:
list_of_display_obj = find_list_of_display_obj(f_base) # tuple
list_of_display_obj = find_list_of_display_obj(f_base)
for k, vals in enumerate(list_of_display_obj):
obj_display, obj_get_color = vals
@@ -120,7 +120,7 @@ def initialize_features(self: "SpeckleProvider", all_coords, all_coord_counts, d
all_coords.extend(coords)
all_coord_counts.append(coord_counts)
obj_get_color_tc = TraversalContext(obj_display, "", item)
obj_get_color_tc = TraversalContext(obj_get_color, "", item)
assign_display_properties(self, feature_new, f_base, obj_get_color_tc)
feature_new["max_height"] = max([c[2] for c in coords])
@@ -169,13 +169,10 @@ def initialize_features(self: "SpeckleProvider", all_coords, all_coord_counts, d
########################
if len(data["features"])==0 and len(data["comments"])==0:
raise ValueError(f"No supported features of type '{self.requested_data_type}' found. Make sure correct type is requested by adding a URL parameter (e.g. '&dataType=points').")
raise ValueError("No supported features found")
time2 = datetime.now()
time_operation = (time2-time1).total_seconds()
self.times["time_creating_features"] = time_operation
# print(f"Creating features time: {time_operation}")
print(f"Creating features time: {(time2-time1).total_seconds()}")
def get_feature_bbox(coords) -> List[float]:
"""Get min max coordinates of the feature."""
-3
View File
@@ -1,3 +0,0 @@
COUNTRY_CODES = ["ru"]
STATES = ['Автономна Республіка Крим', 'Севастополь', 'Донецька область', 'Луганська область']
POSTCODES = [str(i) for i in range(95000,99999)]
@@ -31,7 +31,10 @@ def safe_json_loads(obj: str, obj_id=None) -> Any:
f" int error - falling back to json. \nError: {err}",
SpeckleWarning,
)
return json.loads(obj)
try:
return ujson.loads(obj[:-2])
except:
return json.loads(obj)
class BaseObjectSerializer:
@@ -324,6 +327,7 @@ class BaseObjectSerializer:
# make sure an obj was passed and create dict if string was somehow passed
if not obj:
return
if isinstance(obj, str):
obj = safe_json_loads(obj)
+10 -13
View File
@@ -85,7 +85,7 @@ class ServerTransport(AbstractTransport):
self.url = url
self.session = requests.Session()
if self.account.token is not None:
self._batch_sender = BatchSender(
self.url, self.stream_id, self.account.token, max_batch_size_mb=1
@@ -157,28 +157,25 @@ class ServerTransport(AbstractTransport):
id for id in children_found_map if not children_found_map[id]
]
# save headers and assign them back later
headers = self.session.headers
self.session.headers.update(
{
"Accept": "text/plain",
}
)
# Get the new children
endpoint = f"{self.url}/api/getobjects/{self.stream_id}"
r = self.session.post(
endpoint, data={"objects": json.dumps(new_children_ids)}, stream=True
)
r.encoding = "utf-8"
lines = r.iter_lines(decode_unicode=True)
self.session.headers = headers # return previous headers
lines = r.iter_lines(decode_unicode=True, delimiter="},{")
# iter through returned objects saving them as we go
target_transport.begin_write()
for line in lines:
all_lines = [line for _,line in enumerate(lines)]
for i, line in enumerate(all_lines):
if line:
hash, obj = line.split("\t")
hash = line.split('"id": "')[1].split('"')[0]
obj = "{" + line + "}"
if i==0:
obj = obj[2:]
elif i==len(all_lines)-1:
obj = obj[:-2]
target_transport.save_object(hash, obj)
target_transport.save_object(id, root_obj_serialized)
@@ -169,7 +169,7 @@ def get_info_from_comment(comment: Dict, project_id: str, model_id: str) -> Tupl
res_id = model_id
viewer_state = comment["viewerState"]
if viewer_state is not None: # can be None for Replies
position: List[float] = viewer_state["ui"]["selection"]
position: List[float] = viewer_state["ui"]["camera"]["target"]
try:
res_id = viewer_state["resources"]["request"]["resourceIdString"]
except:
@@ -216,19 +216,4 @@ def get_attachment(project_id: str, attachment_id: str, attachment_name: str) ->
raise Exception(
f"Request not successful: Response code {r.status_code}"
)
def set_actions(self: "SpeckleProvider", client: "SpeckleClient", action: str = "GEO receive"):
from specklepy.logging.metrics import track
try:
full_dict = {**self.url_params, **self.times}
full_dict["GIS commit"] = self.commit_gis
full_dict["project_id"] = f"{self.project_id}"
full_dict["sourceHostApp"] = self.sourceApp
full_dict["model"] = f"{self.project_name}, {self.model_name}"
full_dict["time_TOTAL"] = sum([x[1] for x in self.times.items()])
full_dict["model_url"] = self.speckle_url
full_dict["model_country_code"] = self.country_code
track(action, client.account, full_dict)
except Exception as ex:
print(f"_Cannot set action '{action}': {ex}")
pass
+2 -17
View File
@@ -31,7 +31,6 @@ def get_set_url_parameters(self: "SpeckleProvider"):
requested_data_type = item.split("datatype=")[1]
if requested_data_type in ["points", "lines", "polygons", "projectcomments"]:
self.requested_data_type = requested_data_type
self.url_params["url_data_type"] = requested_data_type
except:
raise ValueError(f"Provide valid dataType parameter (points/lines/polygons/projectcomments): {item}")
@@ -40,7 +39,6 @@ def get_set_url_parameters(self: "SpeckleProvider"):
preserve_attributes = item.split("preserveattributes=")[1]
if preserve_attributes in ["true", "false"]:
self.preserve_attributes = preserve_attributes
self.url_params["url_preserve_attributes"] = preserve_attributes
except:
ValueError(f"Provide valid preserverAttributes parameter (true/false): {item}")
@@ -49,27 +47,23 @@ def get_set_url_parameters(self: "SpeckleProvider"):
if isinstance(crs_authid, str) and len(crs_authid)>3:
crsauthid = True
self.crs_authid = crs_authid
self.url_params["url_crs_authid"] = crs_authid
elif "lat=" in item:
try:
lat = float(item.split("lat=")[1])
self.lat = lat
self.url_params["url_lat"] = lat
except:
raise ValueError(f"Invalid Lat input, must be numeric: {item}")
elif "lon=" in item:
try:
lon = float(item.split("lon=")[1])
self.lon = lon
self.url_params["url_lon"] = lon
except:
raise ValueError(f"Invalid Lon input, must be numeric: {item}")
elif "northdegrees=" in item:
try:
north_degrees = float(item.split("northdegrees=")[1])
self.north_degrees = north_degrees
self.url_params["url_north_degrees"] = north_degrees
except:
raise ValueError(f"Invalid northDegrees input, must be numeric: {item}")
elif "limit=" in item:
@@ -77,15 +71,6 @@ def get_set_url_parameters(self: "SpeckleProvider"):
limit = int(item.split("limit=")[1])
if limit>0:
self.limit = limit
self.url_params["url_limit"] = limit
except:
ValueError(f"Invalid limit input, must be a positive integer: {item}")
elif "useragent=" in item:
try:
agent = item.split("useragent=")[1]
self.user_agent = agent
self.url_params["user_agent"] = agent
except:
ValueError(f"Invalid limit input, must be a positive integer: {item}")
@@ -97,8 +82,8 @@ def get_set_url_parameters(self: "SpeckleProvider"):
if crsauthid:
self.lat = str(self.lat) + " (not applied)"
self.lon = str(self.lon) + " (not applied)"
self.north_degrees = 0 # default to 0: rotation ignored when AuthId is used #str(self.north_degrees) + " (not applied)"
self.north_degrees = str(self.north_degrees) + " (not applied)"
# if CRS parameter present, create and assign CRS:
if len(self.crs_authid)>3:
create_crs_from_authid(self, self.crs_authid)
create_crs_from_authid(self)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

+5 -11
View File
@@ -71,7 +71,7 @@
<meta name="language" content="{{ config['server']['language'] }}">
<meta name="description" content="{{ config['metadata']['identification']['title'] }}">
<meta name="keywords" content="{{ config['metadata']['identification']['keywords']|join(',') }}">
<link rel="shortcut icon" href="https://github.com/specklesystems/pygeoapi/blob/dev/pygeoapi/static/img/speckle_geo.png" type="image/x-icon">
<link rel="shortcut icon" href="{{ config['server']['url'] }}/static/img/speckle_geo.png" type="image/x-icon">
<link rel="stylesheet" href="https://unpkg.com/bootstrap@5.1.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="{{ config['server']['url'] }}/static/css/default.css">
<!--[if lt IE 9]>
@@ -109,9 +109,11 @@
title="{{ config['metadata']['identification']['title'] }}" style="height:30px;vertical-align: middle;" />
<b style="text-align:left;padding-left: 10px;">Speckle</b>
</a>
<a href="https://geo.speckle.systems/" target="_blank" style="text-align:left;padding-left: 10px;" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
<p style="text-align:left;padding-left: 10px;" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
<a href="https://geo.speckle.systems/" target="_blank" style="text-align:left;padding-left: 10px;" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
> Geolocating your data
</a>
</a>
</p>
{% if (data["model"] and data["model"]!="") %}
<a href="{{data['speckle_project_url']}}" target="_blank" style="text-align:left;padding-left: 10px;" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
> {{data["project"]}} >
@@ -131,14 +133,6 @@
<ul class="nav nav-pills"> </ul>
</header>
</div>
<div style="max-height:fit-content;margin:0px;padding:0px;background-color: rgb(10,132,255);">
<p style="text-align: center; margin:0px;padding:5px;">
<a href = "https://docs.google.com/forms/d/e/1FAIpQLScKW2pkcWll3deXEwoV_G5ozLtuU06_prw8rf8HFuCk4tmOPQ/viewform?usp=sf_link"
style="color:rgb(255, 255, 255)" target="_blank">We would love to hear your feedback!</a>
</p>
</div>
</div>
<div class="crumbs">
+10 -41
View File
@@ -202,7 +202,7 @@
<tr>
{% set title_field = data.title_field %}
<td data-label="{{ title_field }}">
<a title="{{ ft.properties.get(title_field) }}" href="{{data['speckle_url'].split('/models')[0]}}/models/{{ft.id.split('_')[0]}}" target="_blank">
<a title="{{ ft.properties.get(title_field) }}" href="{{ data['speckle_project_url'] }}/models/{{ft.id.split('_')[0]}}" target="_blank">
{{ ft.properties.get(title_field) | string | truncate( 35 ) }}
</a>
</td>
@@ -335,11 +335,7 @@
{% block extrafoot %}
<script>
try {
document.getElementById("loading_screen").remove();
document.getElementById("loading_screen_band").remove();
}
catch(err) {}
document.getElementById("loading_screen").remove();
// attach even to modeSwitch btn
document.getElementById("modeSwitch").onclick = switchMode;
@@ -396,21 +392,14 @@
L.control.zoom({
position: 'topright'
}).addTo(map);
var tileLayer = new L.TileLayer(
map.addLayer(new L.TileLayer(
'{{ config['server']['map']['url'] }}', {
maxZoom: 22,
minZoom: 12,
attribution: '{{ config['server']['map']['attribution'] | safe }} &copy; Data: <a href="https://speckle.systems/">Speckle Systems</a>'
}
);
));
geojson_data = split_polygons(geojson_data_original);
project_url = ""
try {
project_url = data['speckle_url'].split("/models")[0]
}
catch(err) {}
var items = new L.GeoJSON(geojson_data, {
filter: (feature) => {
@@ -420,7 +409,7 @@
return new L.circleMarker(latlng)
},
onEachFeature: function (feature, layer) {
var url = project_url + '/models/' + feature.id.split("_")[0]
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);
@@ -446,37 +435,18 @@
return new L.marker(latlng)
},
onEachFeature: function (feature, layer) {
var url = project_url + '/models/' + feature.properties.resource_id + '#threadId=' + feature.id;
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]);
// load proper basemap for Speckle models; but only zoomed-out one for empty data
try
{
bounds = group.getBounds();
map.fitBounds(bounds);
tileLayer.addTo(map);
group.addTo(map);
}
catch (err){
tileLayer = new L.TileLayer(
'{{ config['server']['map']['url'] }}', {
maxZoom: 2,
minZoom: 2,
attribution: '{{ config['server']['map']['attribution'] | safe }} &copy; Data: <a href="https://speckle.systems/">Speckle Systems</a>'
}
);
tileLayer.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
};
@@ -705,7 +675,6 @@
longitude: extent[0] + (extent[2]-extent[0])/2,
latitude: extent[1] + (extent[3]-extent[1])/2,
zoom: 22,
minZoom: 12,
pitch: 60,
bearing: 1.469387755102039
},
+1 -4
View File
@@ -9,10 +9,7 @@
</body>
<script>
try {
document.getElementById("loading_screen").remove();
}
catch(err) {}
document.getElementById("loading_screen").remove();
</script>
</html>
+1 -4
View File
@@ -6,9 +6,6 @@
<p>{{ data['description'] }}</p>
</section>
<script>
try {
document.getElementById("loading_screen").remove();
}
catch(err) {}
document.getElementById("loading_screen").remove();
</script>
{% endblock %}
+3 -13
View File
@@ -1,21 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/bootstrap@5.1.3/dist/css/bootstrap.min.css">
</head>
<body>
<div id="loading_screen_band" style="position:absolute;z-index:-1;width:100%;max-height:fit-content;margin:0px;padding:0px;background-color: rgb(10,132,255);">
<p style="text-align: center; margin:0px;padding:15px;">
<a href = "https://docs.google.com/forms/d/e/1FAIpQLScKW2pkcWll3deXEwoV_G5ozLtuU06_prw8rf8HFuCk4tmOPQ/viewform?usp=sf_link"
style="color:rgb(255, 255, 255)" target="_blank">Why not share a feedback while waiting?</a>
</p>
</div>
<div id="loading_screen" style="position: absolute;top:100px;left:0;right:0;width: fit-content;margin-inline: auto;height:200px;">
<img style="height:200px;width:218.6px" src="https://raw.githubusercontent.com/specklesystems/pygeoapi/dev/pygeoapi/static/img/speckle_cube_loading_winter.gif" alt="Loading data.." >
<h3 style="margin-bottom: 0px;text-align: center; color:rgb(40, 127, 209);font-size: x-large;">"I'm on my way!"</h3>
<p style="text-align: right; color:rgb(40, 127, 209)">- your data </p>
<img style="height:200px;width:218.6px" src="https://raw.githubusercontent.com/specklesystems/pygeoapi/dev/pygeoapi/static/img/speckle_cube_loading.gif" alt="Loading data.." >
<h3 style="margin-bottom: 0px;font-family: 'Verdana'; text-align: center; color:rgb(40, 127, 209);font-size: x-large;">"I'm on my way!"</h3>
<p style="font-family: 'Verdana'; text-align: right; color:rgb(40, 127, 209)">- your data </p>
</div>
</body>
-2
View File
@@ -2,7 +2,6 @@ Babel
click
filelock
Flask
geopy==2.4.1
jinja2
jsonschema
pydantic<2.0
@@ -18,4 +17,3 @@ shapely
SQLAlchemy<2.0.0
tinydb
unicodecsv
specklepy==2.19.6
+1 -1
View File
@@ -86,7 +86,7 @@
});
// construnt data URL
var link = "https://geo.speckle.systems/speckle/?speckleUrl=";
var link = "https://geo.speckle.systems/?speckleUrl=";
if (document.getElementById("speckle_model").value!=""){
link += document.getElementById("speckle_model").value.replace(" ", "")
}
+1 -1
View File
@@ -34,7 +34,7 @@
));
(async () => {
const speckle_data = await fetch('https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments', {
const speckle_data = await fetch('https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments', {
headers: {
'Accept': 'application/geo+json'
}
+1 -1
View File
@@ -34,7 +34,7 @@
));
(async () => {
const speckle_data = await fetch('https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=polygons', {
const speckle_data = await fetch('https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=polygons', {
headers: {
'Accept': 'application/geo+json'
}
+2 -2
View File
@@ -32,7 +32,7 @@
(async () => {
const speckle_data2 = await fetch('https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/37d93c5d32&preserveAttributes=true', {
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'
@@ -155,7 +155,7 @@
//map.fitBounds(speckle_layer.getBounds())
const speckle_data = await fetch('https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments', {
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'
+4 -4
View File
@@ -30,12 +30,12 @@
});
(async () => {
//const speckle_data = await fetch('https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=projectcomments', {
//var speckle_url = 'http://localhost:5000/speckle/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/9c43d7569c&limit=1000000&datatype=polygons&preserveattributes=false';
//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 = 'https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/01c4183677&limit=1000000&datatype=polygons&preserveattributes=true';
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/speckle/?speckleUrl=https://app.speckle.systems/projects/5feae56049/models/9c43d7569c&northDegrees=-30&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'
@@ -65,7 +65,7 @@
//////// add Speckle layer
(async () => {
const geojson = await fetch('https://geo.speckle.systems/speckle/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=polygons', {
const geojson = await fetch('https://geo.speckle.systems/?speckleUrl=https://app.speckle.systems/projects/344f803f81/models/5582ab673e&datatype=polygons', {
headers: {
'Accept': 'application/geo+json'
}
-8
View File
@@ -1,8 +0,0 @@
source .venv/bin/activate
export PYGEOAPI_CONFIG="example-config.yml"
export PYGEOAPI_OPENAPI="example-openapi.yml"
export MAPTILER_KEY_SPECKLE="qam9vwl7bVk5tW1oZu46"
export PORT=8000
gunicorn pygeoapi.flask_app:APP --timeout 100000 --access-logfile access_log --error-logfile error_log --capture-output