예제 #1
0
        /// <summary>
        /// Indica a que lado esta el rectangulo respecto de la linea:
        /// - Si == 0, toca la linea o la cruza.
        /// - Si &gt; 0 esta debajo/derecha de la linea.
        /// - Si &lt; 0 esta encima/izquierda de la linea.
        /// </summary>
        public LineSide WhichSide(BoundingBox2d r)
        {
            int[] sides = new int[3];
            foreach (Point2d p in r.GetVertices())
            {
                LineSide lado = this.WhichSide(p);
                sides[(int)lado]++;
            }

            if (sides[(int)LineSide.Middle] > 0)
            {
                // Toca la linea.
                return(LineSide.Middle);
            }
            if ((sides[(int)LineSide.Left] > 0) && (sides[(int)LineSide.Right] > 0))
            {
                // Cruza la linea.
                return(LineSide.Middle);
            }
            if (sides[(int)LineSide.Left] > 0)
            {
                // totalmente a un lado
                return(LineSide.Left);
            }
            // if (sides[(int)Side.Right] > 0)
            // totalmente a un lado
            return(LineSide.Right);
        }
예제 #2
0
        void SplitEdges(QPolygonF poly, QLineF line)
        {
            if (SplitPoly != null)
            {
                SplitPoly.Clear();
            }

            if (EdgesOnLine != null)
            {
                EdgesOnLine.Clear();
            }

            for (int i = 0; i < poly.Count; i++)
            {
                QLineF edge = new QLineF(poly.ElementAtOrDefault(i), poly.ElementAtOrDefault((i + 1) % poly.Count));

                LineSide edgeStartSide = GetSideOfLine(line, edge.p1());
                LineSide edgeEndSide   = GetSideOfLine(line, edge.p2());
                SplitPoly.Add(new PolyEdge(poly[i], edgeStartSide));
                // SplitPoly.push_back(PolyEdge{ poly[i], edgeStartSide});

                if (edgeStartSide == LineSide.On)
                {
                    EdgesOnLine.Add(SplitPoly.LastOrDefault());
                    // EdgesOnLine.push_back(&SplitPoly.back());
                }
                else if (!edgeStartSide.Equals(edgeEndSide) && edgeEndSide != LineSide.On)
                {
                    QPointF ip;
                    ip = edge.intersect(line);
                    // assert(res != QLineF::NoIntersection);
                    if (ip != null)
                    {
                        SplitPoly.Add(new PolyEdge(ip, LineSide.On));
                        // SplitPoly.push_back(PolyEdge{ ip, LineSide::On});
                        EdgesOnLine.Add(SplitPoly.LastOrDefault());
                        // EdgesOnLine.Add(&SplitPoly.back());
                    }
                }
            }

            // connect doubly linked list, except
            // first->prev and last->next
            for (int ii = 0; ii < (SplitPoly.Count - 1); ii++) // .begin(); iter!=std::prev(SplitPoly.end()); iter++)
            // for (auto iter = SplitPoly.begin(); iter != std::prev(SplitPoly.end()); iter++)
            {
                SplitPoly.ElementAtOrDefault(ii).Next     = SplitPoly.ElementAtOrDefault(ii + 1);
                SplitPoly.ElementAtOrDefault(ii + 1).Prev = SplitPoly.ElementAtOrDefault(ii);

                // auto nextIter = std::next(iter);
                // iter.Next = nextIter;
                // nextIter->Prev = &(* iter);
            }

            // connect first->prev and last->next
            SplitPoly.LastOrDefault().Next  = SplitPoly.FirstOrDefault();
            SplitPoly.FirstOrDefault().Prev = SplitPoly.LastOrDefault();
            // SplitPoly.back().Next = &SplitPoly.front();
            // SplitPoly.front().Prev = &SplitPoly.back();
        }
예제 #3
0
        static LineSide GetLineSides(this Rect rect, Line line)
        {
            LineSide flags = LineSide.None;

            foreach (var pos in rect.EachCornerPositions())
            {
                flags |= line.GetSide(pos);
            }
            return(flags);
        }
예제 #4
0
 public PolyEdge(QPointF startPos, LineSide side)
 {
     StartPos   = startPos;
     StartSide  = side;
     Next       = null;
     Prev       = null;
     DistOnLine = (0.0f);
     IsSrcEdge  = (false);
     IsDstEdge  = (false);
     Visited    = (false);
 }
예제 #5
0
 public static LineSide GetOpposite(this LineSide side)
 {
     if (side == LineSide.LeftSide)
     {
         return(LineSide.RightSide);
     }
     else if (side == LineSide.RightSide)
     {
         return(LineSide.LeftSide);
     }
     return(LineSide.Colinear);
 }
예제 #6
0
        private void Gen(List <Polyline> pls, double t, out List <Polyline> outPls, out List <double> areaLis)
        {
            List <Polyline> nextGen  = new List <Polyline>();
            List <double>   nextArea = new List <double>();

            foreach (Polyline pl in pls)
            {
                Point3d[] pts       = pl.ToArray();
                double[]  ptsLength = new double[pts.Length - 1];
                for (int i = 0; i < pts.Length; i++)
                {
                    if (i > 0)
                    {
                        Point3d prev = pts[i - 1];
                        ptsLength[i - 1] = pts[i].DistanceTo(prev);
                    }
                }
                int  maxIdx      = Array.IndexOf(ptsLength, ptsLength.Max());
                Line longestLine = new Line(pts[maxIdx], pts[maxIdx + 1]);


                Vector3d normal       = new Vector3d(longestLine.Direction);
                Point3d  basePoint    = longestLine.PointAt(t);
                Plane    basePlane    = new Plane(basePoint, normal);
                var      intersection = Intersection.CurvePlane(pl.ToPolylineCurve(), basePlane, 0);
                Line     divider      = new Line(intersection[0].PointA, intersection[1].PointA);
                dividers.Add(divider);
                Vector3d dividerDir = divider.Direction;
                Polyline leftPl     = new Polyline();
                Polyline rightPl    = new Polyline();
                for (int i = 0; i < pl.Count; i++)
                {
                    if (X2D(divider, pts[i]) == LineSide.Right)
                    {
                        rightPl.Add(pts[i]);
                    }
                    else if (X2D(divider, pts[i]) == LineSide.Left)
                    {
                        leftPl.Add(pts[i]);
                    }
                }

                ClockDirection cDir  = CalculateClockDirection(pl.ToList());
                LineSide       cSide = X2D(divider, pl.First);
                if (cDir == ClockDirection.Clockwise &&
                    cSide == LineSide.Left)
                {
                    rightPl.Add(divider.From);
                    rightPl.Add(divider.To);
                    rightPl.Add(rightPl[0]);

                    int index = pl.IndexOf(rightPl[0]);
                    leftPl.Insert(index, divider.To);
                    leftPl.Insert(index + 1, divider.From);
                }
                else
                if (cDir == ClockDirection.Counterclockwise &&
                    cSide == LineSide.Left)
                {
                    rightPl.Add(divider.To);
                    rightPl.Add(divider.From);
                    rightPl.Add(rightPl[0]);

                    int index = pl.IndexOf(rightPl[0]);
                    leftPl.Insert(index, divider.From);
                    leftPl.Insert(index + 1, divider.To);
                }
                else
                if (cDir == ClockDirection.Clockwise &&
                    cSide == LineSide.Right)
                {
                    leftPl.Add(divider.To);
                    leftPl.Add(divider.From);
                    leftPl.Add(leftPl[0]);

                    int index = pl.IndexOf(leftPl[0]);
                    rightPl.Insert(index, divider.From);
                    rightPl.Insert(index + 1, divider.To);
                }
                else
                if (cDir == ClockDirection.Counterclockwise &&
                    cSide == LineSide.Right)
                {
                    leftPl.Add(divider.From);
                    leftPl.Add(divider.To);
                    leftPl.Add(leftPl[0]);

                    int index = pl.IndexOf(leftPl[0]);
                    rightPl.Insert(index, divider.To);
                    rightPl.Insert(index + 1, divider.From);
                }
                nextGen.Add(leftPl);
                nextGen.Add(rightPl);

                double areaL = AreaMassProperties.Compute(leftPl.ToPolylineCurve()).Area;
                double areaR = AreaMassProperties.Compute(leftPl.ToPolylineCurve()).Area;
                nextArea.Add(areaL);
                nextArea.Add(areaR);
            }
            areaLis = nextArea;
            outPls  = nextGen;
        }
예제 #7
0
        /// <summary>
        /// Перемещает одну из линий контура на заданное расстояние
        /// </summary>
        /// <param name="loop">Линии первоначального контура</param>
        /// <param name="delta">Положительное значение - смещение наружу, отрицательное - внутрь</param>
        /// <param name="side">Одна из сторон</param>
        /// <returns>Набор линий, в котором одна из линий смещена на расстояние</returns>
        public static List <Curve> MoveLine(List <Curve> lines, double delta, LineSide side)
        {
            List <Line> loop = lines.Cast <Line>().ToList();

            List <Line> sideLines = GetSideLines(loop, side);

            XYZ moveVector = null;

            if (side == LineSide.Top)
            {
                moveVector = new XYZ(0, 0, delta);
            }
            else if (side == LineSide.Bottom)
            {
                moveVector = new XYZ(0, 0, delta);
            }
            else
            {
                List <Line> verticalLines   = loop.Where(i => Math.Abs(i.Direction.Z) == 1).ToList();
                XYZ         directionPoint0 = new XYZ(verticalLines[0].GetEndPoint(0).X, verticalLines[0].GetEndPoint(0).Y, 0);
                XYZ         directionPoint1 = new XYZ(verticalLines[1].GetEndPoint(0).X, verticalLines[1].GetEndPoint(0).Y, 0);

                XYZ wallDirectionVector = getVectorFromTwoPoints(directionPoint1, directionPoint0);
                XYZ normalizedDirection = normalizeVector(wallDirectionVector);

                if (side == LineSide.Left)
                {
                    delta = -delta;
                }

                moveVector = new XYZ(normalizedDirection.X * delta, normalizedDirection.Y * delta, 0);
            }


            foreach (Line curLine in sideLines)
            {
                XYZ p1    = curLine.GetEndPoint(0);
                XYZ p1new = new XYZ(p1.X + moveVector.X, p1.Y + moveVector.Y, p1.Z + moveVector.Z);

                XYZ p2    = curLine.GetEndPoint(1);
                XYZ p2new = new XYZ(p2.X + moveVector.X, p2.Y + moveVector.Y, p2.Z + moveVector.Z);

                Line             mainLineNew = Line.CreateBound(p1new, p2new);
                SearchLineResult res0        = GetJointLineAtEnd(curLine, loop, 0);

                Line prevLineNew = MoveJointLine(res0, moveVector);

                SearchLineResult res1     = GetJointLineAtEnd(curLine, loop, 1);
                Line             nextLine = res1.Line;

                Line nextLineNew = MoveJointLine(res1, moveVector);

                loop[loop.IndexOf(curLine)]   = mainLineNew;
                loop[loop.IndexOf(res0.Line)] = prevLineNew;
                loop[loop.IndexOf(res1.Line)] = nextLineNew;

                /*loop.Remove(curLine);
                 * loop.Remove(res0.Line);
                 * loop.Remove(res1.Line);
                 * loop.Add(mainLineNew);
                 * loop.Add(prevLineNew);
                 * loop.Add(nextLineNew);*/
            }

            return(loop.Cast <Curve>().ToList());
        }
예제 #8
0
        /// <summary>
        /// Возвращает нижнюю или верхнюю горизонтальную линию
        /// </summary>
        /// <param name="lines"></param>
        /// <returns></returns>
        public static List <Line> GetSideLines(List <Line> lines, LineSide side)
        {
            if (side == LineSide.Bottom || side == LineSide.Top)
            {
                List <Line> horizontalLines = lines
                                              .Where(i => CheckDoubleEquals(i.Direction.Z, 0))
                                              .ToList();

                Line   l      = lines.First();
                double heigth = 0;
                if (side == LineSide.Top)
                {
                    heigth = -999999;
                }
                if (side == LineSide.Bottom)
                {
                    heigth = 999999;
                }

                foreach (Line curLine in horizontalLines)
                {
                    double curHeigth = curLine.GetEndPoint(0).Z;
                    if (side == LineSide.Top)
                    {
                        if (curHeigth > heigth)
                        {
                            l      = curLine;
                            heigth = curHeigth;
                        }
                    }
                    else if (side == LineSide.Bottom)
                    {
                        if (curHeigth < heigth)
                        {
                            l      = curLine;
                            heigth = curHeigth;
                        }
                    }
                }

                //определю все линии на такой же высоте
                List <Line> resultLines = horizontalLines
                                          .Where(i => CheckDoubleEquals(i.Origin.Z, l.Origin.Z))
                                          .ToList();

                return(resultLines);
            }
            else
            {
                List <Line> verticalLines     = lines.Where(i => Math.Abs(i.Direction.Z) == 1).ToList();
                Line[]      leftAndRightLines = GetLeftAndRightLine(verticalLines);
                Line        l = null;
                if (side == LineSide.Left)
                {
                    l = leftAndRightLines[0];
                }
                else
                {
                    l = leftAndRightLines[1];
                }

                List <Line> resultLines = verticalLines
                                          .Where(i => CheckDoubleEquals(i.Origin.X, l.Origin.X) && CheckDoubleEquals(i.Origin.Y, l.Origin.Y))
                                          .ToList();

                return(resultLines);
            }
        }
예제 #9
0
        // only support pairs split points
        List <QPolygonF> SplitEdges2(QPolygonF poly, QLineF line)
        {
            if (SplitPoly != null)
            {
                SplitPoly.Clear();
            }

            if (EdgesOnLine != null)
            {
                EdgesOnLine.Clear();
            }

            // line = new QLineF(new QPointF(new PointLatLngAlt(31.840743072180324, 121.46284818649292)), new QPointF(new PointLatLngAlt(31.840615471377312 , 121.46491885185242)));

            for (int i = 0; i < (poly.Count); i++)
            {
                QLineF edge = new QLineF(poly.ElementAtOrDefault(i), poly.ElementAtOrDefault((i + 1) % poly.Count));

                LineSide edgeStartSide = GetSideOfLine(line, edge.p1());
                LineSide edgeEndSide   = GetSideOfLine(line, edge.p2());
                SplitPoly.Add(new PolyEdge(poly[i], edgeStartSide));
                // SplitPoly.push_back(PolyEdge{ poly[i], edgeStartSide});

                // if (edgeStartSide == LineSide.On)
                // {
                //     EdgesOnLine.Add(SplitPoly.LastOrDefault());
                //     // EdgesOnLine.push_back(&SplitPoly.back());
                // }
                // else if (!edgeStartSide.Equals(edgeEndSide) && edgeEndSide != LineSide.On)
                if (!edgeStartSide.Equals(edgeEndSide) && edgeEndSide != LineSide.On)
                {
                    QPointF ip;
                    ip = edge.intersect(line);

                    // assert(res != QLineF::NoIntersection);
                    if (ip != null)
                    {
                        SplitPoly.Add(new PolyEdge(ip, LineSide.On));
                        // SplitPoly.push_back(PolyEdge{ ip, LineSide::On});
                        EdgesOnLine.Add(SplitPoly.LastOrDefault());
                        // EdgesOnLine.Add(&SplitPoly.back());
                    }
                }
            }


            int              poly_in_split_pair = 0;
            List <QPointF>   split_pair         = new List <QPointF>();
            List <QPolygonF> resPolys           = new List <QPolygonF>();
            // connect doubly linked list and split it into pieces poly
            // first->prev and last->next
            QPolygonF split_out   = new QPolygonF();
            QPointF   start_point = new QPointF(new PointLatLng());
            QPointF   end_point   = new QPointF(new PointLatLng());

            int ii = 0;

            for (ii = 0; ii < (SplitPoly.Count); ii++) // .begin(); iter!=std::prev(SplitPoly.end()); iter++)
            // for (auto iter = SplitPoly.begin(); iter != std::prev(SplitPoly.end()); iter++)
            {
                if (SplitPoly.ElementAtOrDefault(ii).StartSide != LineSide.On) // normal points
                {
                    QPointF qp_added = new QPointF(new PointLatLng(SplitPoly.ElementAtOrDefault(ii).StartPos.x(), SplitPoly.ElementAtOrDefault(ii).StartPos.y()));
                    split_out.Add(qp_added);
                }
                else // edge points
                {
                    if (0 == (poly_in_split_pair %= 2)) // new start point, then find out the end point
                    {
                        poly_in_split_pair = 0;


                        QPolygonF split_out2 = new QPolygonF(); // 2nd poly

                        // add start point
                        start_point = new QPointF(new PointLatLng(SplitPoly.ElementAtOrDefault(ii).StartPos.x(), SplitPoly.ElementAtOrDefault(ii).StartPos.y()));
                        split_out.Add(start_point);
                        split_out2.Add(start_point);

                        // find next split point to 1st poly
                        // SplitPoly.ElementAtOrDefault(ii - 1).Next = SplitPoly.ElementAtOrDefault(ii);
                        bool collect_pnt = false;
                        for (int jj = ii + 1; jj < (SplitPoly.Count); jj++) // .begin(); iter!=std::prev(SplitPoly.end()); iter++)
                        {
                            if (collect_pnt)
                            {
                                QPointF qp_added = new QPointF(new PointLatLng(SplitPoly.ElementAtOrDefault(jj).StartPos.x(), SplitPoly.ElementAtOrDefault(jj).StartPos.y()));
                                split_out.Add(qp_added);
                            }
                            else if (SplitPoly.ElementAtOrDefault(jj).StartSide == LineSide.On) // end points
                            {
                                end_point = new QPointF(new PointLatLng(SplitPoly.ElementAtOrDefault(jj).StartPos.x(), SplitPoly.ElementAtOrDefault(jj).StartPos.y()));
                                split_out.Add(end_point);
                                // split_out2.Add(qp_added);
                                collect_pnt = true;
                            }
                            else // 2nd poly
                            {
                                QPointF qp_added = new QPointF(new PointLatLng(SplitPoly.ElementAtOrDefault(jj).StartPos.x(), SplitPoly.ElementAtOrDefault(jj).StartPos.y()));
                                split_out2.Add(qp_added);
                            }
                        }


                        resPolys.Add(split_out);

                        split_out2.Add(end_point);
                        resPolys.Add(split_out2);

                        start_point = new QPointF(new PointLatLng());
                        end_point   = new QPointF(new PointLatLng());
                        split_out   = new QPolygonF();
                        split_out2  = new QPolygonF();
                    }
                    poly_in_split_pair++;
                }


                // auto nextIter = std::next(iter);
                // iter.Next = nextIter;
                // nextIter->Prev = &(* iter);
            }

            // add last poly
            // resPolys.Add(split_out);

            return(resPolys);
        }