/// push cutter with given normal/center/xy_length into contact with Triangle facet

        // general purpose facetPush
//C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#:
//ORIGINAL LINE: bool generalFacetPush(double normal_length, double center_height, double xy_normal_length, const Fiber& fib, Interval& i, const Triangle& t) const
        protected bool generalFacetPush(double normal_length, double center_height, double xy_normal_length, Fiber fib, Interval i, Triangle t)
        {
            bool  result = false;
            Point normal = t.upNormal();       // facet surface normal, pointing up

            if (normal.zParallel())            // normal points in z-dir
            {
                return(result);                //can't push against horizontal plane, stop here.
            }
            normal.normalize();
            Point xy_normal = new Point(normal);

            xy_normal.z = 0;
            xy_normal.xyNormalize();

            //   find a point on the plane from which radius2*normal+radius1*xy_normal lands on the fiber+radius2*Point(0,0,1)
            //   (u,v) locates a point on the triangle facet    v0+ u*(v1-v0)+v*(v2-v0)    u,v in [0,1]
            //   t locates a point along the fiber:             p1 + t*(p2-p1)             t in [0,1]
            //
            //   facet-point + r2 * n + r1* xy_n = fiber-point + r2*Point(0,0,1)
            //   =>
            //   v0+ u*(v1-v0)+v*(v2-v0) + r2 * n + r1* xy_n  = p1 + t*(p2-p1) + r2*Point(0,0,1)
            //
            //   v0x + u*(v1x-v0x) + v*(v2x-v0x) + r2*nx + r1*xy_n.x  = p1x + t*(p2x-p1x)          p2x-p1x==0 for Y-fiber
            //   v0y + u*(v1y-v0y) + v*(v2y-v0y) + r2*ny + r1*xy_n.y  = p1y + t*(p2y-p1y)          p2y-p1y==0 for X-fiber
            //   v0z + u*(v1z-v0z) + v*(v2z-v0z) + r2*nz              = p1z + t*(p2z-p1z) + r2    (p2z-p1z)==0 for XY-fibers!!
            //   X-fiber:
            //   v0x + u*(v1x-v0x) + v*(v2x-v0x) + r2*nx + r1*xy_n.x  = p1x + t*(p2x-p1x)
            //   v0y + u*(v1y-v0y) + v*(v2y-v0y) + r2*ny + r1*xy_n.y  = p1y                    solve these  two for (u,v)
            //   v0z + u*(v1z-v0z) + v*(v2z-v0z) + r2*nz              = p1z + r2               and substitute above for t
            //   or
            //   [ (v1y-v0y)    (v2y-v0y) ] [ u ] = [ -v0y - r2*ny - r1*xy_n.y + p1y     ]
            //   [ (v1z-v0z)    (v2z-v0z) ] [ v ] = [ -v0z - r2*nz + p1z + r2            ]
            //
            //   Y-fiber:
            //   [ (v1x-v0x)    (v2x-v0x) ] [ u ] = [ -v0x - r2*nx - r1*xy_n.x + p1x     ]

            double a;
            double b;
            double c = t.p[1].z - t.p[0].z;
            double d = t.p[2].z - t.p[0].z;
            double e;
            double f = -t.p[0].z - normal_length * normal.z + fib.p1.z + center_height;
            // note: the xy_normal does not have a z-component, so omitted here.

            double u = 0;           // u and v are coordinates of the cc-point within the triangle facet
            double v = 0;

            // a,b,e depend on the fiber:
            if (fib.p1.y == fib.p2.y)
            {             // XFIBER
                a = t.p[1].y - t.p[0].y;
                b = t.p[2].y - t.p[0].y;
                e = -t.p[0].y - normal_length * normal.y - xy_normal_length * xy_normal.y + fib.p1.y;
                if (!GlobalMembers.two_by_two_solver(a, b, c, d, e, f, ref u, ref v))
                {
                    return(result);
                }
                CCPoint cc = new CCPoint(t.p[0] + u * (t.p[1] - t.p[0]) + v * (t.p[2] - t.p[0]));
                cc.type = CCType.FACET;
                if (!cc.isInside(t))
                {
                    return(result);
                }
                // v0x + u*(v1x-v0x) + v*(v2x-v0x) + r2*nx + r1*xy_n.x = p1x + t*(p2x-p1x)
                // =>
                // t = 1/(p2x-p1x) * ( v0x + r2*nx + r1*xy_n.x - p1x +  u*(v1x-v0x) + v*(v2x-v0x)       )
                Debug.Assert(!GlobalMembers.isZero_tol(fib.p2.x - fib.p1.x));                 // guard against division by zero
                double tval = (1.0 / (fib.p2.x - fib.p1.x)) * (t.p[0].x + normal_length * normal.x + xy_normal_length * xy_normal.x - fib.p1.x + u * (t.p[1].x - t.p[0].x) + v * (t.p[2].x - t.p[0].x));
                if (tval < 0.0 || tval > 1.0)
                {
                    Console.Write("MillingCutter::facetPush() tval= ");
                    Console.Write(tval);
                    Console.Write(" error!?\n");
                    //std::cout << " cutter: " << *this << "\n";
                    Console.Write(" triangle: ");
                    Console.Write(t);
                    Console.Write("\n");
                    Console.Write(" fiber: ");
                    Console.Write(fib);
                    Console.Write("\n");
                }
                Debug.Assert(tval > 0.0 && tval < 1.0);
                i.update(tval, cc);
                result = true;
            }
            else if (fib.p1.x == fib.p2.x)
            {             // YFIBER
                a = t.p[1].x - t.p[0].x;
                b = t.p[2].x - t.p[0].x;
                e = -t.p[0].x - normal_length * normal.x - xy_normal_length * xy_normal.x + fib.p1.x;
                if (!GlobalMembers.two_by_two_solver(a, b, c, d, e, f, ref u, ref v))
                {
                    return(result);
                }
                CCPoint cc = new CCPoint(t.p[0] + u * (t.p[1] - t.p[0]) + v * (t.p[2] - t.p[0]));
                cc.type = CCType.FACET;
                if (!cc.isInside(t))
                {
                    return(result);
                }
                Debug.Assert(!GlobalMembers.isZero_tol(fib.p2.y - fib.p1.y));
                double tval = (1.0 / (fib.p2.y - fib.p1.y)) * (t.p[0].y + normal_length * normal.y + xy_normal_length * xy_normal.y - fib.p1.y + u * (t.p[1].y - t.p[0].y) + v * (t.p[2].y - t.p[0].y));
                if (tval < 0.0 || tval > 1.0)
                {
                    Console.Write("MillingCutter::facetPush() tval= ");
                    Console.Write(tval);
                    Console.Write(" error!?\n");
                    Console.Write(" (most probably a user error, the fiber is too short compared to the STL model?)\n");
                }
                Debug.Assert(tval > 0.0 && tval < 1.0);
                i.update(tval, cc);
                result = true;
            }
            else
            {
                Debug.Assert(false);
            }

            return(result);
        }