/// error function for solver
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual double error(double diangle) const
        public virtual double error(double diangle)
        {
            EllipsePosition tmp = new EllipsePosition();

            tmp.setDiangle(diangle);
            return(error(tmp));
        }
        /// offset-ellipse Brent solver

        /// offfset-ellipse solver using Brent's method
        /// find the EllipsePosition that makes the offset-ellipse point be at p
        /// this is a zero of Ellipse::error()
        /// returns number of iterations
        ///
        /// called (only?) by BullCutter::singleEdgeDropCanonical()
        public int solver_brent()
        {
            int             iters = 1;
            EllipsePosition apos  = new EllipsePosition();            // Brent's method requires bracketing the root in [apos.diangle, bpos.diangle]
            EllipsePosition bpos  = new EllipsePosition();

            apos.setDiangle(0.0);
            Debug.Assert(apos.isValid());
            bpos.setDiangle(3.0);
            Debug.Assert(bpos.isValid());
            if (Math.Abs(error(apos)) < DefineConstants.OE_ERROR_TOLERANCE)
            {                                    // if we are lucky apos is the solution
                EllipsePosition1.CopyFrom(apos); // and we do not need to search further.
                find_EllipsePosition2();
                return(iters);
            }
            else if (Math.Abs(error(bpos)) < DefineConstants.OE_ERROR_TOLERANCE)
            {             // or bpos might be the solution?
                EllipsePosition1.CopyFrom(bpos);
                find_EllipsePosition2();
                return(iters);
            }
            // neither apos nor bpos is the solution
            // but root is now bracketed, so we can use brent_zero
            Debug.Assert(error(apos) * error(bpos) < 0.0);
            // this looks for the diangle that makes the offset-ellipse point y-coordinate zero
            double dia_sln = ocl.GlobalMembers.brent_zero(apos.diangle, bpos.diangle, 3E-16, DefineConstants.OE_ERROR_TOLERANCE, this);             // brent_zero.hpp

            EllipsePosition1.setDiangle(dia_sln);
            Debug.Assert(EllipsePosition1.isValid());
            // because we only work with the y-coordinate of the offset-ellipse-point, there are two symmetric solutions
            find_EllipsePosition2();
            return(iters);
        }
        /// set rhs EllipsePosition (s,t) values equal to lhs EllipsePosition
//C++ TO C# CONVERTER NOTE: This 'CopyFrom' method was converted from the original copy assignment operator:
//ORIGINAL LINE: EllipsePosition& operator =(const EllipsePosition &pos)
        public EllipsePosition CopyFrom(EllipsePosition pos)
        {
            s       = pos.s;
            t       = pos.t;
            diangle = pos.diangle;
            return(this);
        }
        /// normal vector at given EllipsePosition
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: Point normal(const EllipsePosition& pos) const
        public new Point normal(EllipsePosition pos)
        {
            // normal at point is:    b s + a t
            Point n = pos.s * b * major_dir + pos.t * a * minor_dir;

            n.normalize();
            return(new ocl.Point(n));
        }
        /// return a normalized normal vector of the ellipse at the given EllipsePosition
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual Point normal(const EllipsePosition& pos) const
        public virtual Point normal(EllipsePosition pos)
        {
            Debug.Assert(pos.isValid());
            Point n = new Point(b * pos.s, a * pos.t, 0);

            n.normalize();
            return(new ocl.Point(n));
        }
        /// error-function for the solver
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: double error(double diangle) const
        public new double error(double diangle)
        {
            EllipsePosition tmp = new EllipsePosition();

            tmp.setDiangle(diangle);
            Point p        = this.oePoint(tmp);
            Point errorVec = target - p;

            return(errorVec.dot(error_dir));
        }
        /// return a point on the ellipse at given EllipsePosition
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual Point ePoint(const EllipsePosition& pos) const
        public virtual Point ePoint(EllipsePosition pos)
        {
            // (s, t) where:  s^2 + t^2 = 1
            // a and b are the orthogonal axes of the ellipse
            // point of ellipse is:  center + a s + b t               s=cos(theta) t=sin(theta)
            // tangent at point is:  -a t + b s
            // normal at point is:    b s + a t
            // point on offset-ellipse:  point on ellipse + offset*normal
            Point p = new Point(center);

            p.x += a * pos.s;             // a is in X-direction
            p.y += b * pos.t;             // b is in Y-direction
            return(new ocl.Point(p));
        }
        /// return a point on the offset-ellipse at given EllipsePosition
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: virtual Point oePoint(const EllipsePosition& pos) const
        public virtual Point oePoint(EllipsePosition pos)
        {
            return(ePoint(pos) + offset * normal(pos));            // offset-point  = ellipse-point + offset*normal
        }
        /// aligned offset-ellipse solver. callsn Numeric::brent_solver()

        // used by BullCutter pushcutter edge-test
        public bool aligned_solver(Fiber f)
        {
            error_dir.CopyFrom(f.dir.xyPerp()); // now calls to error(diangle) will give the right error
            Debug.Assert(error_dir.xyNorm() > 0.0);
            target.CopyFrom(f.p1);              // target is either x or y-coord of f.p1
            // find position(s) where ellipse tangent is parallel to fiber. Here error() will be minimized/maximized.
            // tangent at point is:  -a t + b s = -a*major_dir*t + b*minor_dir*s
            // -at ma.y + bs mi.y = 0   for X-fiber
            // s = sqrt(1-t^2)
            //  -a*ma.y * t + b*mi.y* sqrt(1-t^2) = 0
            //  =>  t^2 = b^2 / (a^2 + b^2)
            double t1 = 0.0;

            if (f.p1.y == f.p2.y)
            {
                t1 = Math.Sqrt(ocl.GlobalMembers.square(b * minor_dir.y) / (ocl.GlobalMembers.square(a * major_dir.y) + ocl.GlobalMembers.square(b * minor_dir.y)));
            }
            else if (f.p1.x == f.p2.x)
            {
                t1 = Math.Sqrt(ocl.GlobalMembers.square(b * minor_dir.x) / (ocl.GlobalMembers.square(a * major_dir.x) + ocl.GlobalMembers.square(b * minor_dir.x)));
            }
            else
            {
                Debug.Assert(false);
            }
            // bracket root
            EllipsePosition tmp            = new EllipsePosition();
            EllipsePosition apos           = new EllipsePosition();
            EllipsePosition bpos           = new EllipsePosition();
            double          s1             = Math.Sqrt(1.0 - ocl.GlobalMembers.square(t1));
            bool            found_positive = false;
            bool            found_negative = false;

            tmp.setDiangle(GlobalMembers.xyVectorToDiangle(s1, t1));
            if (error(tmp.diangle) > 0)
            {
                found_positive = true;
                apos.CopyFrom(tmp);
            }
            else if (error(tmp.diangle) < 0)
            {
                found_negative = true;
                bpos.CopyFrom(tmp);
            }
            tmp.setDiangle(GlobalMembers.xyVectorToDiangle(s1, -t1));
            if (error(tmp.diangle) > 0)
            {
                found_positive = true;
                apos.CopyFrom(tmp);
            }
            else if (error(tmp.diangle) < 0)
            {
                found_negative = true;
                bpos.CopyFrom(tmp);
            }
            tmp.setDiangle(GlobalMembers.xyVectorToDiangle(-s1, t1));
            if (error(tmp.diangle) > 0)
            {
                found_positive = true;
                apos.CopyFrom(tmp);
            }
            else if (error(tmp.diangle) < 0)
            {
                found_negative = true;
                bpos.CopyFrom(tmp);
            }
            tmp.setDiangle(GlobalMembers.xyVectorToDiangle(-s1, -t1));
            if (error(tmp.diangle) > 0)
            {
                found_positive = true;
                apos.CopyFrom(tmp);
            }
            else if (error(tmp.diangle) < 0)
            {
                found_negative = true;
                bpos.CopyFrom(tmp);
            }

            if (found_positive)
            {
                if (found_negative)
                {
                    Debug.Assert(this.error(apos.diangle) * this.error(bpos.diangle) < 0.0);                     // root is now bracketed.
                    double lolim = 0.0;
                    double hilim = 0.0;
                    if (apos.diangle > bpos.diangle)
                    {
                        lolim = bpos.diangle;
                        hilim = apos.diangle;
                    }
                    else if (bpos.diangle > apos.diangle)
                    {
                        hilim = bpos.diangle;
                        lolim = apos.diangle;
                    }
                    double dia_sln  = ocl.GlobalMembers.brent_zero(lolim, hilim, 3E-16, DefineConstants.OE_ERROR_TOLERANCE, this);
                    double dia_sln2 = ocl.GlobalMembers.brent_zero(hilim - 4.0, lolim, 3E-16, DefineConstants.OE_ERROR_TOLERANCE, this);

                    EllipsePosition1.setDiangle(dia_sln);
                    EllipsePosition2.setDiangle(dia_sln2);

                    Debug.Assert(EllipsePosition1.isValid());
                    Debug.Assert(EllipsePosition2.isValid());

                    /*
                     * // FIXME. This assert fails in some cases (30sphere.stl z=0, for example)
                     * // FIXME. The allowed error should probably be in proportion to the difficulty of the case.
                     *
                     * if (!isZero_tol( error(EllipsePosition1.diangle) )) {
                     *  std::cout << "AlignedEllipse::aligned_solver() ERROR \n";
                     *  std::cout << "error(EllipsePosition1.diangle)= "<< error(EllipsePosition1.diangle) << " (expected zero)\n";
                     *
                     * }
                     * assert( isZero_tol( error(EllipsePosition1.diangle) ) );
                     * assert( isZero_tol( error(EllipsePosition2.diangle) ) );
                     */

                    return(true);
                }
            }

            return(false);
        }
Exemple #10
0
        /// ellipse-point at given EllipsePosition
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: Point ePoint(const EllipsePosition& pos) const
        public new Point ePoint(EllipsePosition pos)
        {
            Point p = center + a * pos.s * major_dir + b * pos.t * minor_dir;             // point of ellipse is:  center + a s + b t

            return(new ocl.Point(p));
        }
Exemple #11
0
        /// error function for the solver
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: double error(EllipsePosition& pos) const
        public double error(EllipsePosition pos)
        {
            Point p1 = oePoint(pos);

            return(p1.y);
        }