示例#1
0
        /*
         *      /// string repr
         *      public static std::ostream operator << (std::ostream stream, BullCutter c)
         *      {
         *        stream << "BullCutter(d=" << c.diameter << ", r1=" << c.radius1 << " r2=" << c.radius2 << ", L=" << c.length << ")";
         *        return stream;
         *      }
         *
         * //C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
         * //ORIGINAL LINE: string str() const
         *      public new string str()
         *      {
         *              std::ostringstream o = new std::ostringstream();
         *              o << this;
         *              return o.str();
         *      }
         */


        // push-cutter: vertex and facet handled by base-class
        //  edge handled here
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: bool generalEdgePush(const Fiber& f, Interval& i, const Point& p1, const Point& p2) const
        protected new bool generalEdgePush(Fiber f, Interval i, Point p1, Point p2)
        {
            //std::cout << " BullCutter::generalEdgePush() \n";
            bool result = false;

            if (GlobalMembers.isZero_tol((p2 - p1).xyNorm()))
            {             // this would be a vertical edge
                return(result);
            }

            if (GlobalMembers.isZero_tol(p2.z - p1.z))             // this would be a horizontal edge
            {
                return(result);
            }
            Debug.Assert(Math.Abs(p2.z - p1.z) > 0.0);             // no horiz edges allowed hereafter

            // p1+t*(p2-p1) = f.p1.z+radius2   =>
            double tplane     = (f.p1.z + radius2 - p1.z) / (p2.z - p1.z);         // intersect edge with plane at z = ufp1.z
            Point  ell_center = p1 + tplane * (p2 - p1);

            Debug.Assert(GlobalMembers.isZero_tol(Math.Abs(ell_center.z - (f.p1.z + radius2))));
            Point major_dir = (p2 - p1);

            Debug.Assert(major_dir.xyNorm() > 0.0);

            major_dir.z = 0;
            major_dir.xyNormalize();
            Point          minor_dir    = major_dir.xyPerp();
            double         theta        = Math.Atan((p2.z - p1.z) / (p2 - p1).xyNorm());
            double         major_length = Math.Abs(radius2 / Math.Sin(theta));
            double         minor_length = radius2;
            AlignedEllipse e            = new AlignedEllipse(ell_center, major_length, minor_length, radius1, major_dir, minor_dir);

            if (e.aligned_solver(f))
            {                                     // now we want the offset-ellipse point to lie on the fiber
                Point   pseudo_cc  = e.ePoint1(); // pseudo cc-point on ellipse and cylinder
                Point   pseudo_cc2 = e.ePoint2();
                CCPoint cc         = new CCPoint(pseudo_cc.closestPoint(p1, p2));
                CCPoint cc2        = new CCPoint(pseudo_cc2.closestPoint(p1, p2));
                cc.type  = CCType.EDGE_POS;
                cc2.type = CCType.EDGE_POS;
                Point cl = e.oePoint1() - new Point(0, 0, center_height);
                Debug.Assert(GlobalMembers.isZero_tol(Math.Abs(cl.z - f.p1.z)));
                Point cl2 = e.oePoint2() - new Point(0, 0, center_height);
                Debug.Assert(GlobalMembers.isZero_tol(Math.Abs(cl2.z - f.p1.z)));
                double cl_t  = f.tval(cl);
                double cl_t2 = f.tval(cl2);
                if (i.update_ifCCinEdgeAndTrue(cl_t, cc, p1, p2, true))
                {
                    result = true;
                }
                if (i.update_ifCCinEdgeAndTrue(cl_t2, cc2, p1, p2, true))
                {
                    result = true;
                }
            }
            //std::cout << " BullCutter::generalEdgePush() DONE result= " << result << "\n";
            return(result);
        }
        /// push cutter against a single vertex p
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: bool singleVertexPush(const Fiber& f, Interval& i, const Point& p, CCType cctyp) const
        protected bool singleVertexPush(Fiber f, Interval i, Point p, CCType cctyp)
        {
            bool result = false;

            if ((p.z >= f.p1.z) && (p.z <= (f.p1.z + this.getLength())))
            {                                             // p.z is within cutter
                Point  pq = p.xyClosestPoint(f.p1, f.p2); // closest point on fiber
                double q  = (p - pq).xyNorm();            // distance in XY-plane from fiber to p
                double h  = p.z - f.p1.z;
                Debug.Assert(h >= 0.0);
                double cwidth = this.width(h);
                if (q <= cwidth)
                {                                                                                               // we are going to hit the vertex p
                    double  ofs    = Math.Sqrt(ocl.GlobalMembers.square(cwidth) - ocl.GlobalMembers.square(q)); // distance along fiber
                    Point   start  = pq - ofs * f.dir;
                    Point   stop   = pq + ofs * f.dir;
                    CCPoint cc_tmp = new CCPoint(p, cctyp);
                    i.updateUpper(f.tval(stop), cc_tmp);
                    i.updateLower(f.tval(start), cc_tmp);
                    result = true;
                }
            }
            return(result);
        }
示例#3
0
        // cone is pushed along Fiber f into contact with edge p1-p2
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: bool generalEdgePush(const Fiber& f, Interval& i, const Point& p1, const Point& p2) const
        protected new bool generalEdgePush(Fiber f, Interval i, Point p1, Point p2)
        {
            bool result = false;

            if (GlobalMembers.isZero_tol(p2.z - p1.z))             // guard against horizontal edge
            {
                return(result);
            }
            Debug.Assert((p2.z - p1.z) != 0.0);
            // idea: as the ITO-cone slides along the edge it will pierce a z-plane at the height of the fiber
            // the shaped of the pierced area is either a circle if the edge is steep
            // or a 'half-circle' + cone shape if the edge is shallow (ice-cream cone...)
            // we can now intersect this 2D shape with the fiber and get the CL-points.

            // this is where the ITO cone pierces the z-plane of the fiber
            // edge-line: p1+t*(p2-p1) = zheight
            // => t = (zheight - p1)/ (p2-p1)
            double t_tip = (f.p1.z - p1.z) / (p2.z - p1.z);
            Point  p_tip = p1 + t_tip * (p2 - p1);

            Debug.Assert(GlobalMembers.isZero_tol(Math.Abs(p_tip.z - f.p1.z)));             // p_tip should be in plane of fiber

            // this is where the ITO cone base exits the plane
            double t_base = (f.p1.z + center_height - p1.z) / (p2.z - p1.z);
            Point  p_base = p1 + t_base * (p2 - p1);

            p_base.z = f.p1.z;             // project to plane of fiber
            double L = (p_base - p_tip).xyNorm();

            //if ( L <= radius ){ // this is where the ITO-slice is a circle
            // find intersection points, if any, between the fiber and the circle
            // fiber is f.p1 - f.p2
            // circle is centered at p_base
            double d = p_base.xyDistanceToLine(f.p1, f.p2);

            if (d <= radius)
            {
                // we know there is an intersection point.
                // http://mathworld.wolfram.com/Circle-LineIntersection.html

                // subtract circle center, math is for circle centered at (0,0)
                double dx  = f.p2.x - f.p1.x;
                double dy  = f.p2.y - f.p1.y;
                double dr  = Math.Sqrt(ocl.GlobalMembers.square(dx) + ocl.GlobalMembers.square(dy));
                double det = (f.p1.x - p_base.x) * (f.p2.y - p_base.y) - (f.p2.x - p_base.x) * (f.p1.y - p_base.y);

                // intersection given by:
                //  x = det*dy +/- sign(dy) * dx * sqrt( r^2 dr^2 - det^2 )   / dr^2
                //  y = -det*dx +/- abs(dy)  * sqrt( r^2 dr^2 - det^2 )   / dr^2

                double discr = ocl.GlobalMembers.square(radius) * ocl.GlobalMembers.square(dr) - ocl.GlobalMembers.square(det);
                if (discr >= 0.0)
                {
                    if (discr == 0.0)
                    {                             // tangent case
                        double x_tang = (det * dy) / ocl.GlobalMembers.square(dr);
                        double y_tang = -(det * dx) / ocl.GlobalMembers.square(dr);
                        Point  p_tang = new Point(x_tang + p_base.x, y_tang + p_base.y);                                // translate back from (0,0) system!
                        double t_tang = f.tval(p_tang);
                        if (circle_CC(t_tang, p1, p2, f, i))
                        {
                            result = true;
                        }
                    }
                    else
                    {
                        // two intersection points with the base-circle
                        double x_pos  = (det * dy + Math.Sign(dy) * dx * Math.Sqrt(discr)) / ocl.GlobalMembers.square(dr);
                        double y_pos  = (-det * dx + Math.Abs(dy) * Math.Sqrt(discr)) / ocl.GlobalMembers.square(dr);
                        Point  cl_pos = new Point(x_pos + p_base.x, y_pos + p_base.y);
                        double t_pos  = f.tval(cl_pos);
                        // the same with "-" sign:
                        double x_neg  = (det * dy - Math.Sign(dy) * dx * Math.Sqrt(discr)) / ocl.GlobalMembers.square(dr);
                        double y_neg  = (-det * dx - Math.Abs(dy) * Math.Sqrt(discr)) / ocl.GlobalMembers.square(dr);
                        Point  cl_neg = new Point(x_neg + p_base.x, y_neg + p_base.y);
                        double t_neg  = f.tval(cl_neg);
                        if (circle_CC(t_pos, p1, p2, f, i))
                        {
                            result = true;
                        }

                        if (circle_CC(t_neg, p1, p2, f, i))
                        {
                            result = true;
                        }
                    }
                }
            }

            //} // circle-case

            if (L > radius)
            {
                // ITO-slice is cone + "half-circle"
                // lines from p_tip to tangent points of the base-circle

                // this page has an analytic solution:
                // http://mathworld.wolfram.com/CircleTangentLine.html
                // this page has a geometric construction:
                // http://www.mathopenref.com/consttangents.html

                // circle p_base, radius
                // top    p_tip

                // tangent point at intersection of base-circle with this circle:
                Point p_mid = 0.5 * (p_base + p_tip);
                p_mid.z = f.p1.z;
                double r_tang = L / 2;

                // circle-circle intersection to find tangent-points
                // three cases: no intersection point
                //              one intersection point
                //              two intersection points

                //d is the distance between the circle centers
                Point pd = p_mid - p_base;
                pd.z = 0;
                double dist = pd.xyNorm();                 //distance between the circles

                //Check for special cases which do not lead to solutions we want
                bool case1 = (GlobalMembers.isZero_tol(dist) && GlobalMembers.isZero_tol(Math.Abs(radius - r_tang)));
                bool case2 = (dist > (radius + r_tang));                           //no solution. circles do not intersect
                bool case3 = (dist < Math.Abs(radius - r_tang));                   //no solution. one circle is contained in the other
                bool case4 = (GlobalMembers.isZero_tol(dist - (radius + r_tang))); // tangent case
                if (case1 || case2 || case3 || case4)
                {
                }
                else
                {
                    // here we know we have two solutions.

                    //Determine the distance from point 0 to point 2
                    // law of cosines (http://en.wikipedia.org/wiki/Law_of_cosines)
                    // rt^2 = d^2 + r^2 -2*d*r*cos(gamma)
                    // so cos(gamma) = (rt^2-d^2-r^2)/ -(2*d*r)
                    // and the sought distance is
                    // a = r*cos(gamma) = (-rt^2+d^2+r^2)/ (2*d)
                    double a = (-ocl.GlobalMembers.square(r_tang) + ocl.GlobalMembers.square(radius) + ocl.GlobalMembers.square(dist)) / (2.0 * dist);
                    Debug.Assert(a >= 0.0);

                    Point v2 = p_base + (a / dist) * pd;                     // v2 is the point where the line through the circle intersection points crosses the line between the circle centers.
                    //Determine the distance from v2 to either of the intersection points
                    double h = Math.Sqrt(ocl.GlobalMembers.square(radius) - ocl.GlobalMembers.square(a));
                    //Now determine the offsets of the intersection points from point 2
                    Point ofs = new Point(-pd.y * (h / dist), pd.x * (h / dist));
                    // now we know the tangent-points
                    Point tang1 = v2 + ofs;
                    Point tang2 = v2 - ofs;
                    if (cone_CC(tang1, p_tip, p_base, p1, p2, f, i))
                    {
                        result = true;
                    }
                    if (cone_CC(tang2, p_tip, p_base, p1, p2, f, i))
                    {
                        result = true;
                    }
                }
            }             // end circle+cone case

            return(result);
        }