Opened 12 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 strk, 12 years ago

Priority: mediumlow

Could also be ST_SignedArea or ST_SignedSquaredArea.

.. or could be that topology should get down one level

comment:2 by strk, 12 years ago

Note that I found a limit in the "construct full polygon, and apply ForceRHR" idea in that LineMerge won't let you construct self-touching rings, thus make it impossible at the moment to construct the polygon. See ticket #1500 for a solution to that problem.

comment:3 by robe, 11 years ago

Cc: strk added

what is this?

comment:4 by strk, 11 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 robe, 11 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:6 by strk, 11 years ago

Milestone: PostGIS 2.1.0PostGIS Future

Future..

comment:7 by remic, 9 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 strk, 9 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 remic, 9 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 remic, 9 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 strk, 9 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 remic, 9 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

comment:13 by robe, 7 years ago

Milestone: PostGIS FuturePostGIS Fund Me

Milestone renamed

Note: See TracTickets for help on using tickets.