Beispiel #1
0
 public static Line2D ParseLine(string lineText)
 {
     string[] splitLine = lineText.Split(' ');
     Line2D line = new Line2D();
     try
     {
         line.Start = new Vector3<double>(double.Parse(splitLine[0]), double.Parse(splitLine[1]), 1);
         line.End = new Vector3<double>(double.Parse(splitLine[2]), double.Parse(splitLine[3]), 1);
     }
     catch (FormatException ex)
     {
         Console.WriteLine("ERROR: Line in incorrect format!");
         Console.WriteLine(ex.ToString());
     }
     return line;
 }
        // Using the cohen sutherland algorithm
        private Line2D ClipLine(Line2D line)
        {
            Line2D newLine = new Line2D();
            newLine.Start = new Vector3<double>(line.Start[0], line.Start[1], 1);
            newLine.End = new Vector3<double>(line.End[0], line.End[1], 1);
            BitCodes code1 = GetCode(newLine.Start);
            BitCodes code2 = GetCode(newLine.End);
            while (true)
            {
                if ((code1 | code2) == BitCodes.Middle)
                {
                    //Hooray we don't need to clip!
                    return newLine;
                }
                else if ((code1 & code2) != BitCodes.Middle)
                {
                    //Line2D totally outside area
                    return null;
                }
                else
                {
                    //More complicated...
                    //at least one endpoint is outside
                    //Need to check for flipped bits
                    //can use xor
                    byte temp = (byte)(code1 ^ code2);
                    byte bitNumber = 4;
                    //If the codes are not either of the trivial cases, at least one bit must be flipped.
                    //Therefore this loop cannot go infinite
                    while (temp != 1)
                    {
                        temp = (byte)(temp >> 1);
                        bitNumber--;
                    }

                    //Pick which point to work on
                    double x = 0;
                    double y = 0;
                    BitCodes workingCode = code1;
                    switch (bitNumber)
                    {
                        case 1:
                            if ((code2 & BitCodes.Top) != 0)
                                workingCode = code2;
                            // y0 > WT and y1 <= WT
                            // yc = WT
                            // xc = ((WT - y0)/(y1 - y0))*(x1 - x0) + x0
                            x = ((m_yMax - newLine.Start[1]) / (newLine.End[1] - newLine.Start[1])) * (newLine.End[0] - newLine.Start[0]) + newLine.Start[0];
                            y = m_yMax;
                            break;
                        case 2:
                            if ((code2 & BitCodes.Bottom) != 0)
                                workingCode = code2;
                            // y0 < WB and y1 >= WB
                            // yc = WB
                            // xc = ((WB - y0)/(y1 - y0))*(x1 - x0) + x0
                            x = ((m_yMin - newLine.Start[1]) / (newLine.End[1] - newLine.Start[1])) * (newLine.End[0] - newLine.Start[0]) + newLine.Start[0];
                            y = m_yMin;
                            break;
                        case 3:
                            if ((code2 & BitCodes.Right) != 0)
                                workingCode = code2;
                            // x0 > WR and x2 <= WR
                            // xc = WR
                            // yc = ((WR - x0)/(x1 - x0))*(y1 - y0) + y0

                            y = ((m_xMax - newLine.Start[0]) / (newLine.End[0] - newLine.Start[0])) * (newLine.End[1] - newLine.Start[1]) + newLine.Start[1];
                            x = m_xMax;
                            break;
                        case 4:
                            if ((code2 & BitCodes.Left) != 0)
                                workingCode = code2;
                            // x0 < WL and x1 >= WL
                            // xc = WL
                            // yc = ((WL - x0)/(x1 - x0))*(y1 - y0) + y0

                            y = ((m_xMin - newLine.Start[0]) / (newLine.End[0] - newLine.Start[0])) * (newLine.End[1] - newLine.Start[1]) + newLine.Start[1];
                            x = m_xMin;
                            break;
                    }
                    if (code1 == workingCode)
                    {
                        newLine.Start[0] = x;
                        newLine.Start[1] = y;
                        code1 = GetCode(newLine.Start);
                    }
                    else
                    {
                        newLine.End[0] = x;
                        newLine.End[1] = y;
                        code2 = GetCode(newLine.End);
                    }
                }
            }
        }
 //Functions that are commented "Based on textbook algorithm" were inspired by ntroduction to Computer Graphics(Foley, Van Dam, et al)
 //All these functions rely on the polygon being specified in counterclockwise vertex ordering.
 //Based on textbook algorithm
 // Calculates the intersection of the line formed by two vertices and a line.
 private Vector3<double> Intersect(Vector3<double> begin, Vector3<double> end, Line2D clipEdge)
 {
     Vector3<double> ret = new Vector3<double>();
     if (clipEdge.Start.Y == clipEdge.End.Y)
     {
         ret.X = begin.X + (clipEdge.Start.Y - begin.Y) * (end.X - begin.X) / (end.Y - begin.Y);
         ret.Y = clipEdge.Start.Y;
     }
     else
     {
         ret.X = clipEdge.Start.X;
         ret.Y = begin.Y + (clipEdge.Start.X - begin.X) * (end.Y - begin.Y) / (end.X - begin.X);
     }
     return ret;
 }
 //Based on textbook algorithm
 //Implements the sutherlandHodgman polygon clipping algorithm. This function will only
 //clip the polygon against one clip edge at a time. Therefore, to clip the entire polygon, we feed the output
 //of this command into the input of another call to this with a different clip edge and keep
 // doing this until we run out of clip edges
 private List<Vector3<double>> SutherlandHodgman(List<Vector3<double>> inVertices, Line2D clipEdge)
 {
     List<Vector3<double>> output = new List<Vector3<double>>();
     Vector3<double> s = inVertices.Last();
     Vector3<double> p;
     for(int i = 0; i < inVertices.Count; i++)
     {
         p = inVertices[i];
         if (Inside(p, clipEdge))
         {
             if (Inside(s, clipEdge))
             {
                 output.Add(p);
             }
             else
             {
                 output.Add(Intersect(s, p, clipEdge));
                 output.Add(p);
             }
         }
         else if(Inside(s, clipEdge))
         {
             output.Add(Intersect(s, p, clipEdge));
         }
         s = p;
     }
     return output;
 }
 //Based on textbook algorithm
 //Determines if a point is inside a given line (inside defined as being to the left of the clipEdge while oriented in the direction of the clip edge)
 private bool Inside(Vector3<double> test, Line2D clipEdge)
 {
     if (clipEdge.End.X > clipEdge.Start.X)
         if (test.Y >= clipEdge.Start.Y)
             return true;
     if (clipEdge.End.X < clipEdge.Start.X)
         if (test.Y <= clipEdge.Start.Y)
             return true;
     if (clipEdge.End.Y > clipEdge.Start.Y)
         if (test.X <= clipEdge.End.X)
             return true;
     if (clipEdge.End.Y < clipEdge.Start.Y)
         if (test.X >= clipEdge.End.X)
             return true;
     return false;
 }