Opened 6 years ago

Closed 4 years ago

Last modified 4 years ago

#2034 closed enhancement (fixed)

ST_3DClosestPoint with mixed dimensionality in input values

Reported by: nicklas Owned by: nicklas
Priority: high Milestone: PostGIS 2.2.0
Component: postgis Version: trunk
Keywords: Cc:

Description (last modified by nicklas)

In the example in #2032, there is input of 2d and 3d. ST_3DClosestPoint then by design assumes that the 2d value have a zero Z-value. But I guess it is more like undefined.

So I think that the most correct solution maybe is to handle the POINT(6 0) in ST_3DClosestPoint function as a infinite vertical line crossing POINT(6 0). Then the answer would be what strk expects in #2032.

I want feedback before I try to do anything about it.

Change History (21)

comment:1 Changed 6 years ago by nicklas

Description: modified (diff)

comment:2 Changed 6 years ago by nicklas

Milestone: PostGIS 2.0.2PostGIS 2.1.0

comment:3 Changed 6 years ago by robe

I'd like to throw an error as I think comparing a 2D and 3D is highly illogical and anyone who does it is probably misinformed and should be told to use ST_ClosestPoint.

pramsey says the same force to 0 exists in &&& so the problem seems more pervasive. I'd wait off on doing anything.

comment:4 Changed 6 years ago by strk

My case is ClosestPoint?(line, point) -- we're looking for a point _on_ the line. If the line is 2d the closest point should be 2d, if the line is 3d the closest point should be 3d. Do you see any lack of generality in the above statement ?

comment:5 Changed 6 years ago by strk

Also, another concern I have is with the 2d/2d input. Current function returns 3d in any case (with Z set to zero) but I'm sure the user would want 2d in that case.

I think having the first argument drive output makes the most sense:

  • 3d/3d -> 3d
  • 3d/2d -> 3d
  • 2d/3d -> 2d
  • 2d/2d -> 2d

comment:6 Changed 6 years ago by nicklas

Strk

St_3dclosestpoint returns a point on the line, but not the point you want since it calculates the 2d point with zero z-value.

I think it would make sense to handle the z value as undefined instead. Than we should find the closest point from any z value. And as I understand this that is the value you would like?

The way to practically do it would be to calculate the 2d closest point and interpolate the z value from the vertex before and after the found closest point.

But I think that I disagree that there should be a difference in dimentionality depending the order of the arguments. That is because st_closestpoint is just the startpoint of st_shortestline.

What we choose here about how to handle missing z values should also affect st_3ddistance.

comment:7 Changed 6 years ago by robe

just my 2c. I agree that ST_ClosestPoint should ALWAYS return a 2D point. That's what we say it does. That's what it should. In the case of ST_ClosestPoint, there is no ambiguity even with 2D / 3D since it will always ignore the Z anyway.

For the 3D Closest Point. It should always return a 3D point and in case of 3d/2D operations -- that operation should simply be undefined.

My concern with making any assumptions here is that it's well undefined and open to endless debate. The idea of making a 2D point into a 3D line is just wrong because it's no longer a point and you end up with a shortest line being mixed dimension. The idea of a 2D point existing in 3D space (with 0 for Z) is also wrong. NULL (undefined) is not the same as infinity nor should it be.

comment:8 Changed 6 years ago by robe

Slight correction to my previous statement. I odn't like the infinite line idea because your shortest line / ST_3DClosestPoint for one side case ends up returning an object that is not on the point. And what pretell will you do when someone asks for a 3D Point / 2 Polygon - you have an infinite polyhedral?

I don't like the current 0 case either because there isn't any reason in my mind why Z=0 is different from any other Z. So in short Z should be like NULL, not 0 and NOT inifinity when not specified.

The answer to an undefined element make the whole operation undefined. That to me was one of the benefits of breaking out 3D functions from 2D. so we don't have to entertain these ambiguous questions.

comment:9 Changed 6 years ago by nicklas

I see the logic Regina, and I guess you are right.

I just want to point out that the idea of handling undefined z-value as any z-value is quite simple. We don't have to deal with infinite polyhedrals in calculations. What we then would do is just make a 2d-calculation. That would give us the correct 2d-point. The z-value will be the same for both start and end-point of the shortestline in this special case of mixed dimension. That is because the 2d geometry will have the same shape on every "z-level". Then the shortestline must be horizontal (I guess).

This would be a true 2.5D behavior. But I agree that putting a z-value on a closestpoint or shortestline on a 2d geometry is quite dirty.

But that will make it harder for Sandro.

Do we have any function to interpolate the z-value of a point on a line or polygon? Or maybe that could be a solution to do what he wants. To do a 2d-calculation and add the z-value "manually".

comment:10 Changed 6 years ago by strk

I'm adding the Z "manually" already. Using ST_Translate (didn't find anything better). No interpolation (but ST_Intersecion supports interpolation).

comment:11 Changed 6 years ago by robe

The logical place where I would think this should happen would be in one of our Force functions:

http://www.postgis.org/documentation/manual-2.0SVN/ST_Force_3D.html http://www.postgis.org/documentation/manual-2.0SVN/ST_Force_3DZ.html

It would be nice if those functions took an extra argument like the Z to force to or something to use for interpolation.

BTW: I noticed these functions don't conform to our naming standard.

Wondering if its time to fix that and also in the process throw in an extra arg that allows you to specify the Z to force to. Seems silly it just goes to 0.

comment:12 Changed 6 years ago by robe

Milestone: PostGIS 2.1.0PostGIS Future

comment:13 Changed 4 years ago by strk

See related discussion about mixing dimensionality in #3045 and http://lists.osgeo.org/pipermail/postgis-devel/2015-February/024759.html

comment:14 Changed 4 years ago by strk

See also #3056 for related discussion about mixed dimensions in ST_3DDistance. According to the recent settlements (missing dimensions are infinite) an ST_3DClosestPoint(3d, 2d) should be returning a 2d point because "distance" (and thus "closeness") is only determined by the 2d component, the 3rd being always at distance=0.

comment:15 Changed 4 years ago by strk

Milestone: PostGIS FuturePostGIS 2.2.0

Regina, I've filed #3057 for adding the optional parameters to the ForceXXX functions (which now have correct naming, see #2748

comment:16 Changed 4 years ago by nicklas

Priority: mediumhigh

comment:17 Changed 4 years ago by strk

On re-reading my comment:14 I changed my mind. ST_3DClosestPoint(3d, 2d) could legitimately return a 3D point as the vertically-infinite geometry to be projected could intersect the reference geometry at a known height.

Treating 2D as having an infinite Z, as suggested in the original submission, is the key here.

comment:18 Changed 4 years ago by robe

FWIW treating 2D as having infinite Z makes the most sense to me.

comment:19 Changed 4 years ago by strk

I noticed ST_3DDistance() is also assuming Z=0 for 2D input, that one should also be changed, right ?

select st_3ddistance('POINT(0 0)'::geometry, 'POINT(0 0 2)'::geometry); -- 2

should instead be 0

comment:20 Changed 4 years ago by nicklas

Resolution: fixed
Status: newclosed

Fixed in r13802 and r13803

Here is the deal: For distance calculations: reverts to 2d calculation. That should give the same answer as "any" z-value on geometry with unknown z-value.

For shortest line calculations: The side of the shortestline without input of z-value will get the same z-value as the other side.

For furthestline: This one is ugly, but the side of the furthest line without input of z-value gets maximun float value as z-value FLT_MAX

For closest point: Same as shortest line.

This is done with shortestline, longest line and closest point by first doing a 2d calculation. Then creating a long vertical line (z-value from FLT_MIN to FLT_MAX) at the resulting point with unknown z-value and then running that line against the original geometry with z-value in the 3d-calculation.

I'm quite happy with the solution, but how does it compare to the behavior of sfcgal-versions?

I close it. Reopen if there is disagreement abut the solution.

comment:21 Changed 4 years ago by robe

Hmm I didn't think SFCgal implemented the ST_3DClosest family of functions.

Anyway you solution seems fine, however sing this is a change in behavior, can you please put in a

Changed: 2.1.9 note in the docs just in case someone was relying on the old broken behavior.

Note: See TracTickets for help on using tickets.