Пример #1
0
        /// 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));
        }
Пример #2
0
        /// 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);
        }
Пример #3
0
        /// 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));
        }
Пример #4
0
        /// 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);
        }