# Make lwgeom_mindist3d solid aware #373

Closed
wants to merge 19 commits into from

## Conversation

Member

### Komzpa commented Feb 11, 2019

 Perform raycast to check if we're completely inside. Lets us remove SFCGAL counterparts completely. https://trac.osgeo.org/postgis/ticket/4278
``` Make lwgeom_mindist3d solid aware ```
`Perform raycast to check if we're completely inside.`
``` c551db1 ```
reviewed
 } static inline int lwgeom_solid_contains_lwgeom(const LWGEOM *solid, const LWGEOM *g)

#### Komzpa Feb 12, 2019

Author Member

@mhugo can you have a look, is there something obvious that I missed here?

### mhugo commented Feb 12, 2019

 @Komzpa Thanks ! Isn't there a possible problem when the start point of the geometry to test has the same x,y as one of the vertex of the solid ? In this case, lwpoly_contains_point will return true for each touching polygon, which could double the number of intersections. This will say a point is outside a solid when it is inside.
Member Author

### Komzpa commented Feb 12, 2019

 @mhugo true, this can happen. Is there a simple way to fix this corner case? It's not enough to just check for vertex equality - a thing can be on some diagonal edge. Technically ptarray_contains_point inside lwpoly_contains_point can output LW_BOUNDARY as hit test result. Probably I can teach lwpoly_contains_point to pass it outside and then count all the LW_BOUNDARY's as half-hits?

### mhugo commented Feb 12, 2019

 @Komzpa Probably I can teach lwpoly_contains_point to pass it outside and then count all the LW_BOUNDARY's as half-hits? Half counting is not enough I think. There are situations where the ray may hit the intersection vertex of 3 polygons, or 4 polygons, or even more ... In 2D, the crossing test for intersection uses an orientation to distinguish edge cases. See http://geomalgorithms.com/a03-_inclusion.html for example. Another possible issue: what happens if the solid contains a polygon that is parallel to the Z axis and the ray intersects it ? Converting it to 2D will result in a point or linestring that will get ignored, right ?
Member Author

### Komzpa commented Feb 12, 2019

 Okay. So how about just printing a warning on LW_BOUNDARY with a ticket link then, and deal with it when someone actually hits it? :) Another option I see is to wrap it into a loop that will perform random rotation of both shapes each time LW_BOUNDARY happens. It feels like in finite-length solids with non-zero distance from interior point to edge there has to be a rotation that will hit only insides of polygons.
added 2 commits Feb 12, 2019
``` Merge remote-tracking branch 'upstream/svn-trunk' into ticket-4278 ```
``` c8de726 ```
``` Randomly skew geometry in a loop if ray coincides with boundary ```
``` 394f921 ```
Member Author

### Komzpa commented Feb 12, 2019

 @mhugo check it out - I'm now randomly skewing geometry if ray hits boundary until it doesn't. Do you maybe have a test case?

### mhugo commented Feb 13, 2019

 @Komzpa I don't really like when an algorithm relies on randomness to finish ... But, apparently CGAL does something similar (see https://doc.cgal.org/latest/Polygon_mesh_processing/classCGAL_1_1Side__of__triangle__mesh.html). Some test cases that triggers the rotations would be welcomed indeed.
reviewed
 if (is_boundary) { /* randomly skew a bit and restart*/ double cx = lwrandom_uniform()-0.5;

#### mwtoews Feb 13, 2019 • edited

To make this random, `lwrandom_set_seed(0)` should be done once somewhere at the top of the `while` loop.

#### Algunenano Feb 13, 2019

Member

At the same time, `ST_3DIntersects` can't be IMMUTABLE if it relies on random behaviour. Could always setting the same seed be the way to go as it doesn't need true randomness, just a series of pseudo-random numbers?

#### mhugo Feb 13, 2019

The randomness is not supposed to change the result. It will change the execution time, not the result. So immutable could stay I think.
However, I agree we do not need true randomness here.

added 2 commits Feb 13, 2019
``` fix leak ```
``` a03942d ```
``` add a box with a hat test ```
``` 3b58c92 ```
Member Author

### Komzpa commented Feb 13, 2019

 @mhugo added a box with a box on top of it aligned with a box inside along Z. Skew is hit now and resolves the case. Any other cases?

### mhugo commented Feb 14, 2019

 @Komzpa Thanks. I would say a last one when the ray hits a vertical face. Something like this (in 2D): The solid could be: ``````select st_astext(st_extrude(st_translate('polygon((0 0 1,0 0 2,1 0 -1,0 0 -1,-1 0 -1,-1 0 1,0 0 1))',0,-1,0),0,2,0)); => POLYHEDRALSURFACE Z (((0 -1 1,-1 -1 1,-1 -1 -1,0 -1 -1,1 -1 -1,0 -1 2,0 -1 1)),((0 1 1,0 1 2,1 1 -1,0 1 -1,-1 1 -1,-1 1 1,0 1 1)),((0 -1 1,0 1 1,-1 1 1,-1 -1 1,0 -1 1)),((-1 -1 1,-1 1 1,-1 1 -1,-1 -1 -1,-1 -1 1)),((-1 -1 -1,-1 1 -1,0 1 -1,0 -1 -1,-1 -1 -1)),((0 -1 -1,0 1 -1,1 1 -1,1 -1 -1,0 -1 -1)),((1 -1 -1,1 1 -1,0 1 2,0 -1 2,1 -1 -1)),((0 -1 2,0 1 2,0 1 1,0 -1 1,0 -1 2))) `````` and the point: `POINT(0 0 0)`
``` Add test case by Hugo Mercier ```
``` 4b1b5a3 ```
Member Author

### Komzpa commented Feb 14, 2019

 If I ST_Tesselate the input the code's not yet working, investigating.
Member Author

### Komzpa commented Feb 15, 2019

 Okay. This works for polyhedrals but not TINS, about which it gets a message. Adding TIN can't be just simple "if POLYGONTYPE || TRIANGLETYPE" as memory layout of TRIANGLE and POLYGON is different (which is not obvious when you count (()) in representation that are aligned with POLYGON).
added 12 commits Feb 15, 2019
``` Triangle clipping test and review ```
``` 6e818e9 ```
``` debug print for null pointer pointarrays ```
``` 5b20fd0 ```
``` Triangle distance functions ```
``` 491de62 ```
``` Change triangle and polygon clamping ```
``` ff2c073 ```
``` git-cola partial commit reduplicates body, remove copy ```
``` dd3def2 ```
``` Remove debug prints ```
``` c4da2b5 ```
``` Add triangle tests ```
``` e738832 ```
``` More triangle options ```
``` 6be0488 ```
``` more TIN tests found lost lwgeom_startpoint support for TIN ```
``` 054efa4 ```
``` refresh copyrights ```
``` 2d5e764 ```
``` more hit tests ```
``` ca4e5b0 ```
``` format ```
``` 58a3f2a ```
``` Check inverses for 3D too ```
``` 958f2f7 ```

### strk closed this in ``` 3abc9a2 ```Feb 16, 2019

referenced this pull request Feb 16, 2019