iTwin / itwinjs-core

Monorepo for iTwin.js Library
https://www.itwinjs.org
MIT License
582 stars 210 forks source link

Need a 3-point ellipse constructor #6794

Open dassaf4 opened 1 month ago

dassaf4 commented 1 month ago

Booster needs to construct an ellipse (Arc3d) through 3 points like MicroStation does.

Though 3 general points define a circle (cf. Arc3d.createCircularStartMiddleEnd), this is not enough information to specify a non-circular ellipse. However, if we constrain two of the points to lie on opposite ends of an axis of the ellipse, the construction is possible.

dassaf4 commented 1 month ago

Probably should backport this to native, as the construction does not exist there.

saeeedtorabi commented 2 weeks ago

if we constrain two of the points to lie on opposite ends of an axis of the ellipse, the construction is possible.

1- How can we force the constrain? Would you please provide more info on this?

2- TS code only supports circle. I assume we need to port back ellipse construction from native to TS, right?

dassaf4 commented 2 weeks ago

Yes, this issue remains open for backport of the new iTwin method. I added a new "Needs backport" status for issues like this, so I've updated its status. The 3pt ellipse construction assumes first and third points are on an axis, and middle point is somewhere else on the arc. If the 3 points are all equidistant from another point, a circle is created, but this just falls out of the math; we don't special case it. In general, if you want to create a circle, it's more convenient to use other methods. But it would be a good test to add: given 3 points on a circle, with first and last on a diameter, both 3pt methods should yield the same circle (geometrically if not parametrically)!

saeeedtorabi commented 2 weeks ago

1- I thought more about ellipse with 3pt. Isnt it super easy? If you have points A, B, and C connect a line from A to C and find the middle point on that line (call it M). Then M would be ellipse center, MC would be vector0, and MB vector90.

2- I'm confused! Do we need to port Arc3d.createCircularStartMiddleEnd from TS to native or not? Isnt bsiDEllipse3d_constructFillet in dellipse3d.cpp that method?

3- Do we need a new method to create an arc using 3pt in native (and TS)? What is bsiDEllipse3d_initFrom3DPoint3dOnArc in dellipse3d.cpp then?

dassaf4 commented 2 weeks ago
  1. Try it! I think you'll find that A and C will not end up on opposite sides of an axis of the resulting ellipse, which is not what the caller expects.
  2. No. Arc3d.createCircularStartMiddleEnd already exists in native code as DEllipse3d::InitFromPointsOnArc. The native method bsiDEllipse3d_constructFillet creates a circular arc of specified radius that "rounds the corner" of a 3-pt linestring. What I believe we don't yet have in native is an analog of the new iTwin method Arc3d.createStartMiddleEnd, which creates a general arc (not necessarily circular!) where first and third points are on an axis of the full ellipse. I could be wrong... the native geomlibs libraries are full of hidden gems! But I do know that MicroStation's elliptical arc tool does not use a geomlibs function for this construction; it uses a 2D constraint solver, which is overkill.
  3. iTwin already had a 3pt circular arc method (Arc3d.createCircularStartMiddleEnd); to address this issue I added the new 3pt elliptical arc method (Arc3d.createStartMiddleEnd). Nothing more is needed for iTwin for this issue. Native already has a 3pt circular arc method (in imodel-native it is DEllipse3d::InitFromPointsOnArc, in PPBase, it is bsiDEllipse3d_initFrom3DPoint3dOnArc). Native most likely does not have an analog of the new iTwin method Arc3d.createStartMiddleEnd, and so this issue is now tracking that backport.