Skip to content

Commit ebb5c46

Browse files
authored
Merge pull request #116 from STEMLab/projection/optimize
02/25 optimize projection sql
2 parents 27b890f + e9446ca commit ebb5c46

2 files changed

Lines changed: 123 additions & 121 deletions

File tree

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# IndoorGML API
1+
# IndoorFeature API
22

3-
IndoorGML api is a RESTful api implementation of the **OGC IndoorGML 2.0** standard, designed to align with **OGC API - Features** standards. This api extends the pygeoapi framework to provide specialized service layers for indoor environments.
3+
IndoorFeature api is a RESTful api implementation of the **OGC IndoorGML 2.0** standard, designed to align with **OGC API - Features** standards. This api extends the pygeoapi framework to provide specialized service layers for indoor environments.
44

55

66
### Naming
77

8-
This API is referred to as the **IndoorGML API** because it implements
8+
This API is referred to as the **IndoorFeature API** because it implements
99
the IndoorGML conceptual model, including spatial subdivision, topology,
1010
layering, and duality relationships.
1111

@@ -71,12 +71,10 @@ pip install -r requirements-indoor.txt
7171
pip install -e .
7272
# Start Docker Containers
7373
docker-compose up -d --build
74-
export PYGEOAPI_CONFIG=pygeoapi-config.yml
75-
export PYGEOAPI_OPENAPI=openAPI/indoorgmlapi_bundled.yml
7674

77-
pygeoapi serve
75+
./start.sh
7876
```
7977

80-
### 2. Environment Startup
78+
### 3. Testing api
8179
We recommand to use a swagger UI for testing api.
8280

pygeoapi/provider/postgresql_indoordb.py

Lines changed: 118 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import json
2-
import random
32
import datetime
43
import psycopg2
54
import logging
65
from functools import partial
76
from dateutil.parser import parse as dateparse
8-
import pytz
97
from pygeoapi.util import format_datetime
108
from psycopg2.extras import Json, RealDictCursor, NamedTupleCursor
119
import re
@@ -1168,61 +1166,64 @@ def _post_primal_members(self, collection_pk:int, feature_pk:int, layer_pk:int,
11681166
# If there is no 2D geometry but 3D, project 3D to 2D geometry
11691167
LOGGER.debug("Project geometry 3D to 2D ")
11701168
sql_project_shell = """
1171-
WITH faces AS (
1172-
SELECT
1173-
c.id,
1174-
s.shell_idx,
1175-
f.face
1176-
FROM cell_space_n_boundary c
1177-
CROSS JOIN LATERAL jsonb_array_elements(c."3D_geometry"->'coordinates')
1178-
WITH ORDINALITY AS s(shell, shell_idx)
1179-
CROSS JOIN LATERAL jsonb_array_elements(s.shell) AS f(face)
1180-
WHERE c."3D_geometry" IS NOT NULL
1181-
AND c.type = 'space'
1182-
AND c."2D_geometry" IS NULL
1183-
AND c.thematiclayer_id = %s
1184-
),
1185-
proj AS (
1186-
SELECT
1187-
id,
1188-
shell_idx,
1189-
ST_SetSRID(
1190-
ST_Force2D(
1191-
ST_GeomFromGeoJSON(
1192-
jsonb_build_object(
1193-
'type', 'Polygon',
1194-
'coordinates',
1195-
CASE
1196-
-- if face is already [ring,...], keep it; else wrap to [ring]
1197-
WHEN jsonb_typeof(face->0->0) = 'array' THEN face
1198-
ELSE jsonb_build_array(face)
1199-
END
1200-
)::text
1201-
)
1202-
),
1203-
0
1204-
) AS g2d
1205-
FROM faces
1206-
),
1207-
u AS (
1208-
SELECT
1209-
id,
1210-
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx = 1) ) AS ext2d,
1211-
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx > 1) ) AS int2d
1212-
FROM proj
1213-
GROUP BY id
1214-
)
1215-
UPDATE cell_space_n_boundary c
1216-
SET "2D_geometry" =
1217-
CASE
1218-
WHEN u.int2d IS NULL THEN u.ext2d
1219-
ELSE ST_Difference(u.ext2d, u.int2d)
1220-
END
1221-
FROM u
1222-
WHERE c.id = u.id
1223-
AND c.thematiclayer_id = %s;
1224-
1225-
"""
1169+
WITH faces AS (
1170+
SELECT
1171+
c.id,
1172+
s.shell_idx,
1173+
f.face
1174+
FROM cell_space_n_boundary c
1175+
CROSS JOIN LATERAL jsonb_array_elements(c."3D_geometry"->'coordinates')
1176+
WITH ORDINALITY AS s(shell, shell_idx)
1177+
CROSS JOIN LATERAL jsonb_array_elements(s.shell) AS f(face)
1178+
WHERE c."3D_geometry" IS NOT NULL
1179+
AND c.type = 'space'
1180+
AND c."2D_geometry" IS NULL
1181+
AND c.thematiclayer_id = %s
1182+
AND (
1183+
s.shell_idx = 1
1184+
OR jsonb_array_length(c."3D_geometry"->'coordinates') > 1
1185+
)
1186+
),
1187+
proj AS (
1188+
SELECT
1189+
id,
1190+
shell_idx,
1191+
ST_SetSRID(
1192+
ST_Force2D(
1193+
ST_GeomFromGeoJSON(
1194+
jsonb_build_object(
1195+
'type', 'Polygon',
1196+
'coordinates',
1197+
CASE
1198+
-- if face is already [ring,...], keep it; else wrap to [ring]
1199+
WHEN jsonb_typeof(face->0->0) = 'array' THEN face
1200+
ELSE jsonb_build_array(face)
1201+
END
1202+
)::text
1203+
)
1204+
),
1205+
0
1206+
) AS g2d
1207+
FROM faces
1208+
),
1209+
u AS (
1210+
SELECT
1211+
id,
1212+
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx = 1) ) AS ext2d,
1213+
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx > 1) ) AS int2d
1214+
FROM proj
1215+
GROUP BY id
1216+
)
1217+
UPDATE cell_space_n_boundary c
1218+
SET "2D_geometry" =
1219+
CASE
1220+
WHEN u.int2d IS NULL THEN u.ext2d
1221+
ELSE ST_Difference(u.ext2d, u.int2d)
1222+
END
1223+
FROM u
1224+
WHERE c.id = u.id
1225+
AND c.thematiclayer_id = %s;
1226+
"""
12261227
cur.execute(sql_project_shell,(layer_pk,layer_pk))
12271228

12281229
return dual_cell, dual_boundary
@@ -1992,63 +1993,66 @@ def post_primal_member(self, collection_id:str, feature_id:str, layer_id:str, da
19921993

19931994
# project cellspace's 3D geometry to 2D if it has no 2D geometry.
19941995
LOGGER.debug("Project geometry 3D to 2D ")
1995-
sql_projection = """
1996-
WITH faces AS (
1997-
SELECT
1998-
c.id,
1999-
s.shell_idx,
2000-
f.face
2001-
FROM cell_space_n_boundary c
2002-
CROSS JOIN LATERAL jsonb_array_elements(c."3D_geometry"->'coordinates')
2003-
WITH ORDINALITY AS s(shell, shell_idx)
2004-
CROSS JOIN LATERAL jsonb_array_elements(s.shell) AS f(face)
2005-
WHERE c."3D_geometry" IS NOT NULL
2006-
AND c.type = 'space'
2007-
AND c."2D_geometry" IS NULL
2008-
AND c.id = %s
2009-
),
2010-
proj AS (
2011-
SELECT
2012-
id,
2013-
shell_idx,
2014-
ST_SetSRID(
2015-
ST_Force2D(
2016-
ST_GeomFromGeoJSON(
2017-
jsonb_build_object(
2018-
'type', 'Polygon',
2019-
'coordinates',
2020-
CASE
2021-
-- if face is already [ring,...], keep it; else wrap to [ring]
2022-
WHEN jsonb_typeof(face->0->0) = 'array' THEN face
2023-
ELSE jsonb_build_array(face)
2024-
END
2025-
)::text
2026-
)
2027-
),
2028-
0
2029-
) AS g2d
2030-
FROM faces
2031-
),
2032-
u AS (
2033-
SELECT
2034-
id,
2035-
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx = 1) ) AS ext2d,
2036-
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx > 1) ) AS int2d
2037-
FROM proj
2038-
GROUP BY id
2039-
)
2040-
UPDATE cell_space_n_boundary c
2041-
SET "2D_geometry" =
2042-
CASE
2043-
WHEN u.int2d IS NULL THEN u.ext2d
2044-
ELSE ST_Difference(u.ext2d, u.int2d)
2045-
END
2046-
FROM u
2047-
WHERE c.id = u.id
2048-
AND c.id = %s;
2049-
2050-
"""
2051-
cur.execute(sql_projection,(new_internal_id, new_internal_id))
1996+
sql_project_shell = """
1997+
WITH faces AS (
1998+
SELECT
1999+
c.id,
2000+
s.shell_idx,
2001+
f.face
2002+
FROM cell_space_n_boundary c
2003+
CROSS JOIN LATERAL jsonb_array_elements(c."3D_geometry"->'coordinates')
2004+
WITH ORDINALITY AS s(shell, shell_idx)
2005+
CROSS JOIN LATERAL jsonb_array_elements(s.shell) AS f(face)
2006+
WHERE c."3D_geometry" IS NOT NULL
2007+
AND c.type = 'space'
2008+
AND c."2D_geometry" IS NULL
2009+
AND c.thematiclayer_id = %s
2010+
AND (
2011+
s.shell_idx = 1
2012+
OR jsonb_array_length(c."3D_geometry"->'coordinates') > 1
2013+
)
2014+
),
2015+
proj AS (
2016+
SELECT
2017+
id,
2018+
shell_idx,
2019+
ST_SetSRID(
2020+
ST_Force2D(
2021+
ST_GeomFromGeoJSON(
2022+
jsonb_build_object(
2023+
'type', 'Polygon',
2024+
'coordinates',
2025+
CASE
2026+
-- if face is already [ring,...], keep it; else wrap to [ring]
2027+
WHEN jsonb_typeof(face->0->0) = 'array' THEN face
2028+
ELSE jsonb_build_array(face)
2029+
END
2030+
)::text
2031+
)
2032+
),
2033+
0
2034+
) AS g2d
2035+
FROM faces
2036+
),
2037+
u AS (
2038+
SELECT
2039+
id,
2040+
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx = 1) ) AS ext2d,
2041+
ST_UnaryUnion( ST_Collect(g2d) FILTER (WHERE shell_idx > 1) ) AS int2d
2042+
FROM proj
2043+
GROUP BY id
2044+
)
2045+
UPDATE cell_space_n_boundary c
2046+
SET "2D_geometry" =
2047+
CASE
2048+
WHEN u.int2d IS NULL THEN u.ext2d
2049+
ELSE ST_Difference(u.ext2d, u.int2d)
2050+
END
2051+
FROM u
2052+
WHERE c.id = u.id
2053+
AND c.thematiclayer_id = %s;
2054+
"""
2055+
cur.execute(sql_project_shell,(new_internal_id, new_internal_id))
20522056
# 4. FIX: Commit only if we get here successfully
20532057
self.connection.commit()
20542058
return new_str_id

0 commit comments

Comments
 (0)