/// <summary> /// Indica a que lado esta el rectangulo respecto de la linea: /// - Si == 0, toca la linea o la cruza. /// - Si > 0 esta debajo/derecha de la linea. /// - Si < 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); }
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(); }
static LineSide GetLineSides(this Rect rect, Line line) { LineSide flags = LineSide.None; foreach (var pos in rect.EachCornerPositions()) { flags |= line.GetSide(pos); } return(flags); }
public PolyEdge(QPointF startPos, LineSide side) { StartPos = startPos; StartSide = side; Next = null; Prev = null; DistOnLine = (0.0f); IsSrcEdge = (false); IsDstEdge = (false); Visited = (false); }
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); }
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; }
/// <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()); }
/// <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); } }
// 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); }