Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New distance queries #66

Open
radevgit opened this issue Jul 30, 2023 · 20 comments
Open

New distance queries #66

radevgit opened this issue Jul 30, 2023 · 20 comments

Comments

@radevgit
Copy link

Hi,
Do you have any plans to implement distance queries for other geometric objects like: SEG-ARC, ARC-ARC ?

@davideberly
Copy link
Owner

The distance between 2 segments in any dimension is implemented in DistSegmentSegment.h.

I am currently implementing distance algorithms between line/ray/segment and circle/arc. The line/ray/segment-circle code is finished, including unit testing. I will post this shortly. I need to implement line/ray/segment-arc. This should take me another 1 or 2 days.

@owai1980
Copy link

owai1980 commented Jul 31, 2023 via email

@radevgit
Copy link
Author

radevgit commented Jul 31, 2023

Thanks David,
I checked before the DistSegmentSegment.h, and I was surprised how complex is the algorithm.
My naive thinking was, that is should be simple than intersection algorithm.
Thanks again for the fast response.

@davideberly
Copy link
Owner

The document Robust Computation of Distance Between Line Segmants has a couple of examples that show the straightforward algorithm, when computed using floating-point arithmetic, can have gross errors because of subtractive cancellation. In particular, see Example 2. If you use the straightforward algorithm computing with rational arithmetic, all is well.

The file I mentioned has a function ComputeRobust(...), where I attempt to avoid the problem with subtractive cancellation. The idea is reasonable in the floating-point era when you do not have a fused-multiply-add instruction. That instruction computes fma(x,y,z) = x*y+z with 1 rounding step. Without such an instruction, w = x*y has 1 rounding step and w+z has 1 rounding step for a total of 2 rounding steps, which generally leads to more rounding error.

With the fma instruction, you can "fix" the subtractive cancellation in expressions x*y-z*w. The implementation is in my Math.h file, functions RobustDOP. The idea is due to Professor William Kahan On the Cost of Floating-Point Computation
Without Extra-Precise Arithmetic
and succinctly mentioned by Matt Pharr Accurate Differences of Products with Kahan’s Algorithm. At some time I will revisit the segment-segment distance code and modify it to use this paradigm.

@davideberly davideberly reopened this Jul 31, 2023
@radevgit
Copy link
Author

radevgit commented Aug 1, 2023

Thanks for the references. I learned a lot. Regarding the fused-multiply-add instruction, it should be available std::fma. Also, regarding such numerical issues, I noted somewhere in the code the use of dot(v0, v1) and sqrt for the length of a vector. There are claims that hypot uses robust algorithm for the same. It looks from some comments, that the hypot also use fma operations.

@davideberly
Copy link
Owner

The IEEE Standard for Floating-Point Arithmetic 754-2019 includes the requirement that implementations provide fusedMultiplyAdd. For hypotenuse in 2D (squared length of vectors), you can compute xx+yy using the same idea I mentioned. Implementation is RobustSOP (Robust Sum Of Products) in Math.h. The replacement of DOP and SOP will take some time in my code.

@mgamito
Copy link

mgamito commented Aug 2, 2023 via email

@davideberly
Copy link
Owner

I appreciate your input, thank you.

Software implementations of floating-point functions have that curse. To follow the standard, the logic can be quite complicated and expensive to compute without hardware support. My focus lately has been on robust computations, much of this using rational arithmetic (which effectively is floating-point implemented in software), so I suppose much of my code is "woefully slow" when using rational support.

I added to my short-term TODO list the ability to "discard" FMA operations using a preprocessor define GTE_DISCARD_FMA. If not defined, std::fma(x,y,z) is used. If defined, x*y+z is computed instead with 2 floating-point operations. Longer term I could add a FMA software implementation using the ideas of BSNumber<UIntegerFP32> for N sufficiently large and then add a preprocessor define GTE_USE_SOFTWARE_FMA. But of course this will be slow.

Given you are using modern NVIDIA technology and a render farm, I would have thought a primary goal is to replace old hardware with new hardware. It seems strange that the GPU support of NanoVDB accesses GPU hardware (that has fma), but the underlying CPU is too old for fma. However, if you have a large number of old computers, I can see why hardware upgrade is not desireable.

@radevgit
Copy link
Author

radevgit commented Aug 12, 2023

For hypotenuse in 2D (squared length of vectors), you can compute x_x+y_y using the same idea I mentioned. Implementation is RobustSOP (Robust Sum Of Products) in Math.h. The replacement of DOP and SOP will take some time in my code.

Here, I found the actual implementation in glibc, that seems to use some additional tricks:
hypot

@davideberly
Copy link
Owner

I have posted 2D distance queries for line-circle, ray-circle, segment-circle, line-arc, ray-arc, segment-arc. I have not yet posted arc-arc queries (need to think about this one a bit).

@davideberly
Copy link
Owner

I pressed the wrong button, did not mean to close the issue. Reopening it. I am currently working on the 2D distance queries for circle-circle, circle-arc, and arc-arc.

@davideberly davideberly reopened this Aug 29, 2023
@owai1980
Copy link

owai1980 commented Aug 29, 2023 via email

@tmatthey
Copy link

tmatthey commented Jun 3, 2024

I did an implementation of seg-arc and arc-arc. I calculate first the line/circle-circle distance(s), then remove the distance(s) not on of seg or cricle. Since you can assume for circles that the points are on the circle you can check if the arc's angle is equal to the sum angles of endpoints with the point, same for point on seg with the distance. Then calculate all distances between the end points seg/arc-arc and take the minimum. I can provide some tests if needed.

@davideberly
Copy link
Owner

Sorry for taking so long to respond. Sure, send me tests if you like. I already have seg-arc distance code. Does this not work for you?

@tmatthey
Copy link

Line3Circle3 and Circle3Circle3 works and cannot point on any issues. Well done! I was referring to examples for Segment3Arc3 and Arc3Arc3. I can provide you with my examples, input and distance.

@davideberly
Copy link
Owner

Ah. I lost the context of the dimension (3 in your case) and saw that I had distance code for 2D segment/arc. Technical support questions (github issues and private emails) have been consuming much of my time, especially when I have to revise the PDF documentation. I finally cleared out that queue and can finish up the 3D segment/arc code I had started locally. Yes, any examples you want to send me can be incorporated into the unit tests. Thank you.

@tmatthey
Copy link

Good. I'll send you a list of Line/Circle3 - Circle3 with start & end points and the min distance as C++.

@davideberly
Copy link
Owner

Sorry, I am confused. I thought you were going to provide unit-test examples for distances for Segment3-Arc3 and Arc3-Arc3? I already have unit-tested implementations for Line3-Circle3 and Circle3-Circle3.

@tmatthey
Copy link

My tests are seg/arc - arc in 3d. I was looking for arc3, found only arc2. So the examples are seg / arc ones🙂

@tmatthey
Copy link

I found 130 tests together for Segement3-Arc3 and Arc3-Arc3 distance queries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants