Opened 13 years ago
Last modified 7 years ago
#1498 new enhancement
ST_CrossProduct ?
Reported by: | strk | Owned by: | pramsey |
---|---|---|---|
Priority: | low | Milestone: | PostGIS Fund Me |
Component: | postgis | Version: | master |
Keywords: | Cc: | strk |
Description
Not sure I really want this, but seems a good thing to have for computing winding of topological rings w/out constructing the full polygon, applying ForceRHR and comparing with ST_OrderingEquals.
Change History (13)
comment:1 by , 13 years ago
Priority: | medium → low |
---|
comment:2 by , 13 years ago
comment:4 by , 12 years ago
It's to compute a ring's winding by only looking at edges that compose it. Probably only useful for topology.
comment:5 by , 12 years ago
well are you going to do something about it in 2.1.0? If not push and then push back if you happen to get to it.
comment:7 by , 10 years ago
Function (expect a ring of signed edge)
DROP FUNCTION IF EXISTS topology.ST_SignedArea( ring_of_edges INT[] ) ; CREATE OR REPLACE FUNCTION topology.ST_SignedArea( ring_of_edges INT[] , OUT signedArea FLOAT)
AS
$BODY$
/ @brief given a ring (an ordered set of signed edge_id), compute the sum of angles between nodes */ DECLARE BEGIN
WITH input_data AS (
SELECT r.ordinality, r.value AS s_edge_id, (count(*) over(partition by abs(r.value)) ≠2) as is_simple FROM rc_unnest_with_ordinality(ring_of_edges) as r
) ,joined_to_edge AS (
SELECT ordinality, s_edge_id, edge_id, dmp.geom as pt_geom, path[1] as path FROM input_data as id
LEFT OUTER JOIN bdtopo_topological.edge_data as ed
ON (abs(id.s_edge_id) = ed.edge_id)
, ST_DumpPoints(geom) AS dmp
WHERE s_edge_id <0 AND is_simple = TRUE UNION ALL SELECT ordinality, s_edge_id, edge_id, dmp.geom as pt_geom, -path[1] as path FROM input_data as id
LEFT OUTER JOIN bdtopo_topological.edge_data as ed
ON (abs(id.s_edge_id) = ed.edge_id)
, ST_DumpPoints(geom) AS dmp
WHERE s_edge_id >0 AND is_simple = TRUE
) ,getting_next_node AS (
SELECT ordinality, s_edge_id , pt_geom as pt, COALESCE(lead(pt_geom,1) OVER(w) , first(pt_geom) OVER(w )) as n_pt FROM joined_to_edge WINDOW w AS (ORDER BY ordinality ASC, path ASC)
) SELECT sum( (ST_X(n_pt)-ST_X(pt)) * (ST_Y(n_pt)+ST_Y(pt) )/2.0 ) INTO signedArea FROM getting_next_node ;
RETURN ;
END ; $BODY$
LANGUAGE plpgsql IMMUTABLE STRICT;
comment:8 by , 10 years ago
Is that faster than constructing the polygon and calling ST_IsCCW on it ? (that's what we do currently in topology population function)
comment:9 by , 10 years ago
I don't know if it is faster, but it is totally safe (to precision issue) I don't know how the "polygon is constructed", I could look if you want (which function is it?) I don't think using ST_IsCCW is safe because due to precision issue you could construct a non-simple polygon, and ST_IsCCW may not like it.
If it is slower, I could construct the polygon (safe for precision, but possibly not simple), and call ST_IsCCW
Cheers, Rémi-C
comment:10 by , 10 years ago
I can't find ST_IsCCW. Can you point me toward it so I can investigate please. Cheers, Rémi-C
comment:11 by , 10 years ago
oops sorry I was probably wrong, there's no such function (could be added). I think in current topology code I compare pointwise the original geometry with the result of ST_ForceRHR, which is obviously overkill for big geometries…
comment:12 by , 10 years ago
For the record,
I first wrote a version that used topology node (instead of edge geom node). However SignedArea of linked toplogy node was a bad IsCCW detector because it returned 0 in some simple case(2 edges forming a square = 2 nodes, 0 area, but can be CW or CCW depending on the order). However with a robust function isCCW(point1, point2, point3), I could write a faster version that does't use the edge geom (and would return only orientation, not signed area) .
Cheers, Rémi-C
Could also be ST_SignedArea or ST_SignedSquaredArea.
.. or could be that topology should get down one level