예제 #1
0
        }//end Solve3

        public bool Solve2(double L1, double L2, cPointi target, cPointd J)
        {
            cPointi c1 = new cPointi(list.head.Point.X, list.head.Point.Y); // center of circle 1
            int     nsoln;                                                  // # of solns: 0,1,2,3(infinite)

            nsoln = TwoCircles(c1, L1, target, L2, J);
            return(nsoln != 0);
        }// end Solve2
예제 #2
0
        }//end Solve

        public bool Solve3(double L1, double L2, double L3, cPointi target0)
        {
            cPointi target;
            cPointd Jk;      // coords of kinked joint returned by Solve2
            cPointi J1;      // Joint1 on x-axis
            cPointi Ttarget; // translated target

            target = new cPointi(target0.X, target0.Y);


            System.Diagnostics.Debug.WriteLine("==>Solve3: links = " + L1 + ", " + L2 + ", " + L3);

            Jk = new cPointd(0, 0);

            if (Solve2(L1 + L2, L3, target, Jk))
            {
                firstlinks++;
                nlinks = 2;

                System.Diagnostics.Debug.WriteLine("Solve3: link1=" + (L1 + L2) + ", link2=" + L3 + ", joint=\n");
                LineTo_d(Jk);
                SetAChain(Jk, target);
                return(true);
            }
            else if (Solve2(L1, L2 + L3, target, Jk))
            {
                System.Diagnostics.Debug.WriteLine("Solve3: link1= " + L1 + ", link2= " + (L2 + L3) + ", joint=\n");
                nlinks = 2;
                LineTo_d(Jk);
                SetAChain(Jk, target);
                return(true);
            }
            else
            {   // pin J0 to 0.
                // Shift so J1 is origin.
                //J1.x = L1;   J1.y = 0;
                J1      = new cPointi(L1, 0);
                Ttarget = new cPointi(0, 0);
                SubVec(target, J1, Ttarget);
                if (Solve2(L2, L3, Ttarget, Jk))
                {
                    // Shift solution back to origin.
                    Jk.x += L1;
                    System.Diagnostics.Debug.WriteLine("Solve3: link1=" + L1 + ", link2= " + L2 + ", link3= " + L1 + ", joints=\n");
                    nlinks = 3;
                    LineTo_i(J1);
                    LineTo_d(Jk);
                    SetAChain(Jk, target);
                    cVertex VJ1 = new cVertex(list.head.Point.X + J1.X, list.head.Point.Y);
                    list.InsertBefore(VJ1, list.head.NextVertex);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }//end Solve3
        private bool diagdrawn = true;     //diag-s've been drawn after triang?

        public cPolygoni(cVertexList list)
        {
            this.list = list;
            listcopy  = new cVertexList();
            diaglist  = new cDiagonalList();
            CG        = new cPointd(0, 0);
            intCount  = 0;
            diagdrawn = true;
        }
        /*---------------------------------------------------------------------
        *  SegSegInt: Finds the point of intersection p between two closed
        *  segments ab and cd.  Returns p and a char with the following meaning:
        *  'e': The segments collinearly overlap, sharing a point.
        *  'v': An endpoint (vertex) of one segment is on the other segment,
        *  but 'e' doesn't hold.
        *  '1': The segments intersect properly (i.e., they share a point and
        *  neither 'v' nor 'e' holds).
        *  '0': The segments do not intersect (i.e., they share no points).
        *  Note that two collinear segments that share just one point, an endpoint
        *  of each, returns 'e' rather than 'v' as one might expect.
        *  ---------------------------------------------------------------------*/
        public char SegSegInt(cPointi a, cPointi b, cPointi c, cPointi d, cPointd p, cPointd q)
        {
            double s, t;       /* The two parameters of the parametric eqns. */
            double num, denom; /* Numerator and denoninator of equations. */
            char   code = '?'; /* Return char characterizing intersection. */

            p.x = p.y = 100.0; /* For testing purposes only... */

            denom = a.X * (double)(d.Y - c.Y) +
                    b.X * (double)(c.Y - d.Y) +
                    d.X * (double)(b.Y - a.Y) +
                    c.X * (double)(a.Y - b.Y);

            /* If denom is zero, then segments are parallel: handle separately. */
            if (denom == 0.0)
            {
                return(ParallelInt(a, b, c, d, p, q));
            }

            num = a.X * (double)(d.Y - c.Y) +
                  c.X * (double)(a.Y - d.Y) +
                  d.X * (double)(c.Y - a.Y);
            if ((num == 0.0) || (num == denom))
            {
                code = 'v';
            }
            s = num / denom;
            System.Diagnostics.Debug.WriteLine("SegSegInt: num=" + num + ",denom=" + denom + ",s=" + s);

            num = -(a.X * (double)(c.Y - b.Y) +
                    b.X * (double)(a.Y - c.Y) +
                    c.X * (double)(b.Y - a.Y));
            if ((num == 0.0) || (num == denom))
            {
                code = 'v';
            }
            t = num / denom;
            System.Diagnostics.Debug.WriteLine("SegSegInt: num=" + num + ",denom=" + denom + ",t=" + t);

            if ((0.0 < s) && (s < 1.0) &&
                (0.0 < t) && (t < 1.0))
            {
                code = '1';
            }
            else if ((0.0 > s) || (s > 1.0) ||
                     (0.0 > t) || (t > 1.0))
            {
                code = '0';
            }

            p.x = a.X + s * (b.X - a.X);
            p.y = a.Y + s * (b.Y - a.Y);

            return(code);
        }
예제 #5
0
        //---------------------------------------------------------------------
        //TwoCircles00 assumes circle centers are (0,0) and (a2,0).
        //---------------------------------------------------------------------
        public void TwoCircles00(double r1, double a2, double r2, cPointd p)
        {
            double r1sq, r2sq;

            r1sq = r1 * r1;
            r2sq = r2 * r2;

            // Return only positive-y soln in p.
            p.x = (a2 + (r1sq - r2sq) / a2) / 2;
            p.y = Math.Sqrt(r1sq - p.x * p.x);
        }//end TwoCircles00
예제 #6
0
        public void SetAChain(cPointd Jk, cPointi target)
        {
            cPointi vaux1;
            cPointi vaux2;

            vaux1 = new cPointi(list.head.Point.X, list.head.Point.Y);
            vaux2 = new cPointi(target.X, target.Y);
            list.ClearVertexList();
            list.SetVertex(vaux1.X, vaux1.Y);
            list.SetVertex((int)(Jk.x + .5), (int)(Jk.y + .5));
            list.SetVertex(vaux2.X, vaux2.Y);
        }
예제 #7
0
        }// end Solve2

        //---------------------------------------------------------------------
        //TwoCircles finds an intersection point between two circles.
        //General routine: no assumptions. Returns # of intersections; point in p.
        //---------------------------------------------------------------------

        public int TwoCircles(cPointi c1, double r1, cPointi c2, double r2, cPointd p)
        {
            cPointi c;
            cPointd q;
            int     nsoln = -1;

            // Translate so that c1={0,0}.
            c = new cPointi(0, 0);
            SubVec(c2, c1, c);
            q     = new cPointd(0, 0);
            nsoln = TwoCircles0a(r1, c, r2, p);//p instead of

            // Translate back.
            p.x = p.x + c1.X;
            p.y = p.y + c1.Y;
            return(nsoln);
        }
예제 #8
0
        /*---------------------------------------------------------------------
        *  Prints out the double point of intersection, and toggles in/out flag.
        *  ---------------------------------------------------------------------*/
        public cInFlag InOut(cPointd p, cInFlag inflag, int aHB, int bHA)
        {
            InsertInters(p.x, p.y);

            /* Update inflag. */
            if (aHB > 0)
            {
                inflag.f = cInFlag.Pin; return(inflag);
            }
            else if (bHA > 0)
            {
                inflag.f = cInFlag.Qin; return(inflag);
            }
            else    /* Keep status quo. */
            {
                return(inflag);
            }
        }
예제 #9
0
        }//end TwoCircles0a

        //---------------------------------------------------------------------
        //TwoCircles0b also assumes that the 1st circle is origin-centered.
        //---------------------------------------------------------------------
        public int TwoCircles0b(double r1, cPointi c2, double r2, cPointd p)
        {
            double  a2;         // center of 2nd circle when rotated to x-axis
            cPointd q;          // one solution when c2 on x-axis
            double  cost, sint; // sine and cosine of angle of c2

            // Rotate c2 to a2 on x-axis.
            a2   = Math.Sqrt(Length2(c2));
            cost = c2.X / a2;
            sint = c2.Y / a2;
            q    = new cPointd(0, 0);
            TwoCircles00(r1, a2, r2, q);

            // Rotate back
            p.x = cost * q.x + -sint * q.y;
            p.y = sint * q.x + cost * q.y;

            return(2);
        }
예제 #10
0
        //---------------------------------------------------------------------
        //TwoCircles0a assumes that the first circle is centered on the origin.
        //Returns # of intersections: 0, 1, 2, 3 (inf); point in p.
        //-----------------------------------------------------------------------
        public int TwoCircles0a(double r1, cPointi c2, double r2, cPointd p)
        {
            double dc2;              // dist to center 2 squared
            double rplus2, rminus2;  // (r1 +/- r2)^2
            double f;                // fraction along c2 for nsoln=1

            // Handle special cases.
            dc2     = Length2(c2);
            rplus2  = (r1 + r2) * (r1 + r2);
            rminus2 = (r1 - r2) * (r1 - r2);

            // No solution if c2 out of reach + or -.
            if ((dc2 > rplus2) || (dc2 < rminus2))
            {
                return(0);
            }

            // One solution if c2 just reached.
            // Then solution is r1-of-the-way (f) to c2.
            if (dc2 == rplus2)
            {
                f   = r1 / (double)(r1 + r2);
                p.x = f * c2.X; p.y = f * c2.Y;
                return(1);
            }
            if (dc2 == rminus2)
            {
                if (rminus2 == 0)
                {   // Circles coincide.
                    p.x = r1; p.y = 0;
                    return(3);
                }
                f   = r1 / (double)(r1 - r2);
                p.x = f * c2.X; p.x = f * c2.Y;
                return(1);
            }
            // Two intersections.

            int auxint = TwoCircles0b(r1, c2, r2, p);

            return(auxint);
        }//end TwoCircles0a
예제 #11
0
        //**************************************

        public bool Solven(double x, double y)

        /*Is called when the user drags the last point of the link or releases it.
         * Corresponds to the Solven method in C*/
        {
            double  halfLength; //floor of half os total
            cPointi target;     //point for storing the target
            cPointd Jk;         // coords of kinked joint returned by Solve2
            cPointi J1;         // Joint1 on x-axis



            //create target
            target = new cPointi(x, y);

            //Compute Length array and # of links
            cVertex v0;

            v1 = list.head;

            for (i = 0; i < list.n - 1; i++)
            {
                linklen[i] = (Length(v1.Point, v1.NextVertex.Point) + .5);
                v1         = v1.NextVertex;
            }
            nlinks = list.n - 1;


            //Compute total&half Length

            totLength = 0;

            for (i = 0; i < nlinks; i++)
            {
                totLength += linklen[i];
            }
            halfLength = totLength / 2;

            //Find median link
            if (nlinks > 2)
            {
                L1 = 0;
                for (m = 0; m < nlinks; m++)
                {
                    if ((L1 + linklen[m]) > halfLength)
                    {
                        break;
                    }
                    L1 += linklen[m];
                }//end for

                L2         = linklen[m];
                L3         = totLength - L1 - L2;
                firstlinks = m;
                for (i = 0; i < nlinks; i++)
                {
                    linklenback[i] = linklen[i];
                }
                nlinksback = nlinks;
            }
            else if (nlinks == 2)
            {
                L1 = linklen[0];
                L2 = linklen[1];
                L3 = 0;
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Just one link!!!");
                L1 = L2 = L3 = 0;
            }

            if ((nlinks == 3) && (nlinksback == 0))
            {
                nlinksback = 3;
            }
            if (nlinks == 2)
            {
                Jk = new cPointd(0, 0);
                if (Solve2(L1, L2, target, Jk))
                {
                    System.Diagnostics.Debug.WriteLine("Solve2 for 2 links: link1= " + L1 + ", link2= " + L2 + ", joint=\n");
                    LineTo_d(Jk);
                    SetAChain(Jk, target);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }//end if nlinks==2
            else
            {
                if (Solve3(L1, L2, L3, target))
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }//end Solve
예제 #12
0
 public void LineTo_d(cPointd p)
 {
     System.Diagnostics.Debug.WriteLine(" Line to d" + p.x + ", " + p.y);
 }
 public void Assigndi(cPointd p, cPointi a)
 {
     p.x = a.X;
     p.y = a.Y;
 }
        public char ParallelInt(cPointi a, cPointi b, cPointi c, cPointi d, cPointd p, cPointd q)
        {
            if (!a.Collinear(a, b, c))
            {
                return('0');
            }

            if (Between1(a, b, c) && Between1(a, b, d))
            {
                Assigndi(p, c);
                Assigndi(q, d);
                return('e');
            }
            if (Between1(c, d, a) && Between1(c, d, b))
            {
                Assigndi(p, a);
                Assigndi(q, b);
                return('e');
            }
            if (Between1(a, b, c) && Between1(c, d, b))
            {
                Assigndi(p, c);
                Assigndi(q, b);
                return('e');
            }
            if (Between1(a, b, c) && Between1(c, d, a))
            {
                Assigndi(p, c);
                Assigndi(q, a);
                return('e');
            }
            if (Between1(a, b, d) && Between1(c, d, b))
            {
                Assigndi(p, d);
                Assigndi(q, b);
                return('e');
            }
            if (Between1(a, b, d) && Between1(c, d, a))
            {
                Assigndi(p, d);
                Assigndi(q, a);
                return('e');
            }
            return('0');

            /*
             * if ( Between1( a, b, c ) ) {
             * Assigndi( p, c );
             * return 'e';
             * }
             * if ( Between1( a, b, d ) ) {
             * Assigndi( p, d );
             * return 'e';
             * }
             * if ( Between1( c, d, a ) ) {
             * Assigndi( p, a );
             * return 'e';
             * }
             * if ( Between1( c, d, b ) ) {
             * Assigndi( p, b );
             * return 'e';
             * }
             * return '0';
             */
        }
예제 #15
0
        /*---------------------------------------------------------------------
        * Consult the book for explanations
        *--------------------------------------------------------------------*/
        private void ConvexIntersect(cVertexList P, cVertexList Q, int n, int m)
        /* P has n pointCloud, Q has m pointCloud. */
        {
            /* Initialize variables. */
            a          = new cVertex();
            b          = new cVertex();
            a          = P.head; b = Q.head;
            aa         = ba = 0;
            Origin     = new cPointi(); /* (0,0) */
            inflag     = new cInFlag();
            FirstPoint = true;
            cVertex a1, b1;

            A  = new cPointi();
            B  = new cPointi();
            p  = new cPointd();
            q  = new cPointd();
            p0 = new cPointd();

            do
            {
                /* System.Diagnostics.Debug.WriteLine("Before Advances:a="+a.v.x+","+a.v.y+
                 * ", b="+b.v.x+","+b.v.y+"; aa="+aa+", ba="+ba+"; inflag="+
                 * inflag.f); */
                /* Computations of key variables. */
                a1 = a.PrevVertex;
                b1 = b.PrevVertex;

                SubVec(a.Point, a1.Point, A);
                SubVec(b.Point, b1.Point, B);

                cross = Origin.TriangleSign(Origin, A, B);
                aHB   = b1.Point.TriangleSign(b1.Point, b.Point, a.Point);
                bHA   = a1.Point.TriangleSign(a1.Point, a.Point, b.Point);
                System.Diagnostics.Debug.WriteLine("cross=" + cross + ", aHB=" + aHB + ", bHA=" + bHA);

                /* If A & B intersect, update inflag. */
                code = a1.Point.SegSegInt(a1.Point, a.Point, b1.Point, b.Point, p, q);
                System.Diagnostics.Debug.WriteLine("SegSegInt: code = " + code);

                if (code == '1' || code == 'v')
                {
                    if (inflag.f == cInFlag.Unknown && FirstPoint)
                    {
                        aa         = ba = 0;
                        FirstPoint = false;
                        p0.x       = p.x; p0.y = p.y;
                        InsertInters(p0.x, p0.y);
                    }
                    inflag = InOut(p, inflag, aHB, bHA);
                    System.Diagnostics.Debug.WriteLine("InOut sets inflag=" + inflag.f);
                }

                /*-----Advance rules-----*/

                /* Special case: A & B overlap and oppositely oriented. */
                if ((code == 'e') && (Dot(A, B) < 0))
                {
                    InsertSharedSeg(p, q);
                    return;
                }

                /* Special case: A & B parallel and separated. */
                if ((cross == 0) && (aHB < 0) && (bHA < 0))
                {
                    System.Diagnostics.Debug.WriteLine("P and Q are disjoint.");
                    return;
                }


                /* Special case: A & B collinear. */
                else if ((cross == 0) && (aHB == 0) && (bHA == 0))
                {
                    /* Advance but do not output point. */
                    if (inflag.f == cInFlag.Pin)
                    {
                        b = Advance(b, "ba", inflag.f == cInFlag.Qin, b.Point);
                    }
                    else
                    {
                        a = Advance(a, "aa", inflag.f == cInFlag.Pin, a.Point);
                    }
                }

                /* Generic cases. */
                else if (cross >= 0)
                {
                    if (bHA > 0)
                    {
                        a = Advance(a, "aa", inflag.f == cInFlag.Pin, a.Point);
                    }
                    else
                    {
                        b = Advance(b, "ba", inflag.f == cInFlag.Qin, b.Point);
                    }
                }
                else /* if ( cross < 0 ) */
                {
                    if (aHB > 0)
                    {
                        b = Advance(b, "ba", inflag.f == cInFlag.Qin, b.Point);
                    }
                    else
                    {
                        a = Advance(a, "aa", inflag.f == cInFlag.Pin, a.Point);
                    }
                }
                System.Diagnostics.Debug.WriteLine("After advances:a=(" + a.Point.X + ", " + a.Point.Y +
                                                   "), b=(" + b.Point.X + ", " + b.Point.Y + "); aa=" + aa +
                                                   ", ba=" + ba + "; inflag=" + inflag.f);

                /* Quit when both adv. indices have cycled, or one has cycled twice. */
            } while (((aa < n) || (ba < m)) && (aa < 2 * n) && (ba < 2 * m));

            if (!FirstPoint) /* If at least one point output, close up. */
            {
                InsertInters(p0.x, p0.y);
            }

            /* Deal with special cases: not implemented. */
            if (inflag.f == cInFlag.Unknown)
            {
                System.Diagnostics.Debug.WriteLine("The boundaries of P and Q do not cross.");
                intersection = false;
            }
        }
예제 #16
0
 public void InsertSharedSeg(cPointd p, cPointd q)
 {
     InsertInters((int)p.x, (int)p.y);
     InsertInters((int)q.x, (int)q.y);
 }
예제 #17
0
        char code         = '0';             /* intersection code returned by SegSegInt*/

        public cSegSeg(cVertexList list)
        {
            p         = new cPointd(0, 0);
            this.list = list;
        }