Revision: 56000
          http://sourceforge.net/p/brlcad/code/56000
Author:   phoenixyjll
Date:     2013-07-11 07:58:18 +0000 (Thu, 11 Jul 2013)
Log Message:
-----------
Add arc (including circle) fitting and ellipse (including elliptical arc) 
fitting.

Modified Paths:
--------------
    brlcad/trunk/src/libbrep/intersect.cpp

Modified: brlcad/trunk/src/libbrep/intersect.cpp
===================================================================
--- brlcad/trunk/src/libbrep/intersect.cpp      2013-07-11 03:20:08 UTC (rev 
55999)
+++ brlcad/trunk/src/libbrep/intersect.cpp      2013-07-11 07:58:18 UTC (rev 
56000)
@@ -1851,9 +1851,12 @@
 ON_Curve*
 curve_fitting(ON_Curve* in, double fitting_tolerance, bool delete_curve = 
false)
 {
+    // Fit a *2D* curve into line, arc, ellipse or other comic curves.
+
     if (in == NULL)
        return NULL;
 
+    // Linear fitting
     if (in->IsLinear(fitting_tolerance)) {
        ON_LineCurve *linecurve = new ON_LineCurve(in->PointAtStart(), 
in->PointAtEnd());
        linecurve->ChangeDimension(in->Dimension());
@@ -1861,6 +1864,79 @@
        return linecurve;
     }
 
+    // Arc fitting (including circle)
+    ON_Arc arc;
+    if (in->IsArc(&ON_xy_plane, &arc, fitting_tolerance)) {
+       if (delete_curve) delete in;
+       ON_ArcCurve* arccurve = new ON_ArcCurve(arc);
+       arccurve->ChangeDimension(in->Dimension());
+       return arccurve;
+    }
+
+    double conic[6];
+    double sample_pts[12];
+    int plotres = in->IsClosed() ? 6 : 5;
+    for (int i = 0; i < 6; i++) {
+       ON_3dPoint pt3d = 
in->PointAt(in->Domain().ParameterAt((double)i/plotres));
+       sample_pts[2*i] = pt3d.x;
+       sample_pts[2*i+1] = pt3d.y;
+    }
+    if (ON_GetConicEquationThrough6Points(2, sample_pts, conic, NULL, NULL, 
NULL)) {
+       // It may be a conic.
+       ON_2dPoint ell_center;
+       ON_2dVector ell_A, ell_B;
+       double ell_a, ell_b;
+       // First, fitting an ellipse. It seems that ON_Curve::IsEllipse()
+       // doesn't work, so we use conic fitting first. If this is not ideal,
+       // an alternative solution is to use least square fitting on all
+       // points.
+       if (ON_IsConicEquationAnEllipse(conic, ell_center, ell_A, ell_B, 
&ell_a, &ell_b)) {
+           ON_Plane ell_plane = ON_Plane(ON_3dPoint(ell_center), 
ON_3dVector(ell_A), ON_3dVector(ell_B));
+           ON_Ellipse ell(ell_plane, ell_a, ell_b);
+           int knotcnt = in->SpanCount();
+           double* knots = new double [knotcnt + 1];
+           in->GetSpanVector(knots);
+           int i;
+           double t_min = DBL_MAX, t_max = -DBL_MAX;
+           for (i = 0; i <= knotcnt; i++) {
+               // It may not be a complete ellipse.
+               // We find the domain of its parameter.
+               ON_3dPoint pt = in->PointAt(knots[i]);
+               double t;
+               ON_3dPoint ell_pt;
+               if (!ell.ClosestPointTo(pt, &t))
+                   break;
+               ell_pt = ell.PointAt(t);
+               if (ell_pt.DistanceTo(pt) > fitting_tolerance)
+                   break;
+               t_min = std::min(t, t_min);
+               t_max = std::max(t, t_max);
+           }
+           if (i == knotcnt+1) {
+               // All points are on the ellipse
+               if (in->IsClosed()) {
+                   t_max = ON_PI*2, t_min = 0;
+               }
+               ON_NurbsCurve nurbscurve;
+               ell.GetNurbForm(nurbscurve);
+               // The params of the nurbscurve is between [0, 2*pi]
+               ON_Curve *left = NULL, *right = NULL;
+               if (!ON_NearZero(t_min))
+                   nurbscurve.Split(t_min, left, right);
+               else
+                   right = &nurbscurve;
+               if (right && !ON_NearZero(t_max - 2*ON_PI))
+                   right->Split(t_max, left, right);
+               else
+                   left = right;
+               if (delete_curve) delete in;
+               return left->Duplicate();
+           }
+       }
+    }
+
+    // We have tried all fittings, but none of them succeed.
+    // So we just return the original curve.
     return in;
 }
 

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to