/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.Intersect (ICurve, BoundingRect, out GeoPoint[], out GeoPoint2D[], out double[])"/> /// </summary> /// <param name="curve"></param> /// <param name="uvExtent"></param> /// <param name="ips"></param> /// <param name="uvOnFaces"></param> /// <param name="uOnCurve3Ds"></param> public override void Intersect(ICurve curve, BoundingRect uvExtent, out GeoPoint[] ips, out GeoPoint2D[] uvOnFaces, out double[] uOnCurve3Ds) { if (curve is Line) { GeoPoint ip; if (Plane.Intersect(curve.StartPoint, curve.StartDirection, out ip)) { ips = new GeoPoint[] { ip }; uvOnFaces = new GeoPoint2D[] { PositionOf(ip) }; uOnCurve3Ds = new double[] { curve.PositionOf(ip) }; } else { ips = new GeoPoint[0]; uvOnFaces = new GeoPoint2D[0]; uOnCurve3Ds = new double[0]; } #if DEBUG //GeoPoint[] ipsdbg; //GeoPoint2D[] uvOnFacesdbg; //double[] uOnCurve3Dsdbg; //base.Intersect(curve, out ipsdbg, out uvOnFacesdbg, out uOnCurve3Dsdbg); #endif return; } //else if (curve is IExplicitPCurve3D) //{ // ExplicitPCurve3D epc3d = (curve as IExplicitPCurve3D).GetExplicitPCurve3D(); // double [] res = epc3d.GetPlaneIntersection(Location, DirectionX, DirectionY); // for (int i = 0; i < res.Length; i++) // { // double d = Plane.Distance(epc3d.PointAt(res[i])); // if (i>0) d = Plane.Distance(epc3d.PointAt((res[i]+res[i-1])/2.0)); // } // double dd = Plane.Distance(epc3d.PointAt(epc3d.knots[epc3d.knots.Length - 1])); // for (int i = 0; i < res.Length; i++) // { // res[i] = (res[i] - epc3d.knots[0]) / (epc3d.knots[epc3d.knots.Length - 1] - epc3d.knots[0]); // } //} else { if (curve.GetPlanarState() == PlanarState.Planar) { GeoPoint loc; GeoVector dir; Plane pln = curve.GetPlane(); if (Plane.Intersect(curve.GetPlane(), out loc, out dir)) { ICurve2D c2d = curve.GetProjectedCurve(pln); BoundingRect ext = c2d.GetExtent(); ext.Inflate(ext.Height + ext.Width); // sonst entstehen null-Linien ICurve2D ll = new Line2D(pln.Project(loc), pln.Project(dir), ext); #if DEBUG DebuggerContainer dc = new DebuggerContainer(); dc.Add(c2d); dc.Add(ll); #endif GeoPoint2DWithParameter[] gpp = ll.Intersect(c2d); ips = new GeoPoint[gpp.Length]; uvOnFaces = new GeoPoint2D[gpp.Length]; uOnCurve3Ds = new double[gpp.Length]; for (int i = 0; i < gpp.Length; ++i) { ips[i] = pln.ToGlobal(gpp[i].p); uvOnFaces[i] = PositionOf(ips[i]); uOnCurve3Ds[i] = curve.PositionOf(ips[i]); } } else { ips = new GeoPoint[0]; uvOnFaces = new GeoPoint2D[0]; uOnCurve3Ds = new double[0]; } #if DEBUG //GeoPoint[] ipsdbg; //GeoPoint2D[] uvOnFacesdbg; //double[] uOnCurve3Dsdbg; //base.Intersect(curve, out ipsdbg, out uvOnFacesdbg, out uOnCurve3Dsdbg); #endif return; } } TetraederHull th = new TetraederHull(curve); // alle Kurven müssten eine gemeinsame basis habe, auf die man sich hier beziehen kann // damit die TetraederHull nicht mehrfach berechnet werden muss th.PlaneIntersection(this, out ips, out uvOnFaces, out uOnCurve3Ds); // base.Intersect(curve, out ips, out uvOnFaces, out uOnCurve3Ds); }
private void AddSplittedFace(Face face) { List <ICurve> edgeCurves = new List <ICurve>(); List <ICurve2D> curves2d = new List <ICurve2D>(); #if DEBUG Vertex[] vtx = face.Vertices; bool[] outside = new bool[vtx.Length]; Polyline pln = Polyline.Construct(); for (int i = 0; i < vtx.Length; i++) { outside[i] = outsideVertices.Contains(vtx[i]); pln.AddPoint(vtx[i].Position); } DebuggerContainer dc = new DebuggerContainer(); #endif Edge[] edges = face.AllEdges; // sollte keine Löcher haben for (int i = 0; i < edges.Length; i++) { List <double> positions; if (splitedEdges.TryGetValue(edges[i], out positions)) { List <double> pos = new List <double>(positions); pos.Add(0.0); pos.Add(1.0); pos.Sort(); int startj; Vertex startVertex; ICurve2D c2d = edges[i].Curve2D(face); #if DEBUG dc.Add(c2d, System.Drawing.Color.Red, i); #endif if ((face.Surface.PointAt(c2d.StartPoint) | edges[i].Vertex1.Position) < (face.Surface.PointAt(c2d.StartPoint) | edges[i].Vertex2.Position)) { startVertex = edges[i].Vertex1; } else { startVertex = edges[i].Vertex2; // die Kurve geht andersrum als die Kante, also Kantenschnittpunkte umdrehen pos.Reverse(); } if (outsideVertices.Contains(startVertex)) { startj = 1; } else { startj = 0; } for (int j = startj; j < pos.Count - 1; j += 2) { double pos1 = c2d.PositionOf(face.Surface.PositionOf(edges[i].Curve3D.PointAt(pos[j]))); double pos2 = c2d.PositionOf(face.Surface.PositionOf(edges[i].Curve3D.PointAt(pos[j + 1]))); if (pos2 < pos1) { double tmp = pos1; pos1 = pos2; pos2 = tmp; } ICurve2D trimmed = c2d.Trim(pos1, pos2); curves2d.Add(trimmed); #if DEBUG dc.Add(trimmed, System.Drawing.Color.Blue, i); #endif } } else { if (!outsideVertices.Contains(edges[i].Vertex1)) { #if DEBUG dc.Add(edges[i].Curve2D(face), System.Drawing.Color.Green, i); #endif curves2d.Add(edges[i].Curve2D(face)); } } } List <ICurve2D> lc2d; if (all2DCurves.TryGetValue(face, out lc2d)) { for (int i = 0; i < lc2d.Count; i++) { #if DEBUG dc.Add(lc2d[i], System.Drawing.Color.HotPink, i); #endif // die folgende Kurve mit Start- und Endpunkt anpassen, denn sie ist evtl ungenau... curves2d.Add(lc2d[i]); } } // alle zuletzt hinzugefügten Kurven magnetisch einschnappen lassen for (int i = all2DCurves.Count - lc2d.Count; i < all2DCurves.Count; i++) { AddAndAdjust2DCurve(curves2d, i); } // eigentlich wäre mehr Information vorhanden, als dass man diese Kurven völlig neu sortieren müsste // aber so ist es nun mal einfacher ICurve2D[] acsd = new ICurve2D[curves2d.Count]; for (int i = 0; i < acsd.Length; i++) { acsd[i] = curves2d[i].Clone(); } Reduce2D r2d = new Reduce2D(); r2d.Add(acsd); r2d.OutputMode = Reduce2D.Mode.Paths; ICurve2D[] red = r2d.Reduced; if (red.Length == 1) { Border bdr = new Border(red[0]); SimpleShape ss = new SimpleShape(bdr); Face splitted = Face.MakeFace(face.Surface, ss); resultingFaces.Add(splitted); } //CompoundShape cs = CompoundShape.CreateFromList(acsd, Precision.eps); //if (cs != null && cs.SimpleShapes.Length == 1) //{ // SimpleShape ss = cs.SimpleShapes[0]; // Face splitted = Face.MakeFace(face.Surface, ss); // resultingFaces.Add(splitted); //} //else //{ //} }
public Shell GetInsidePart() { closedBorder.Flatten(); if (!closedBorder.IsClosed) { Line l = Line.Construct(); l.SetTwoPoints(closedBorder.EndPoint, closedBorder.StartPoint); closedBorder.Add(l); } vertexToFace = new Face[closedBorder.CurveCount]; for (int i = 0; i < closedBorder.CurveCount; i++) { Face fc = FindClosestFace(closedBorder.Curve(i).StartPoint); if (fc == null) { throw new SplitShellWithCurvesException(); } vertexToFace[i] = fc; } all2DCurves = new Dictionary <Face, List <ICurve2D> >(); splitedEdges = new Dictionary <Edge, List <double> >(); for (int i = 0; i < vertexToFace.Length; i++) { InsertCurve(i); } // jetzt die Faces beschneiden und eine neue Shell bauen Vertex[] vertices = shell.Vertices; outsideVertices = new Set <Vertex>(); for (int i = 0; i < vertices.Length; i++) { // wenn der Vertex eine Außenkante hat, dann gilt er als außenliegend Edge[] vedges = vertices[i].Edges; for (int j = 0; j < vedges.Length; j++) { if (vedges[j].SecondaryFace == null) { FollowVertex(vertices[j]); } } } #if DEBUG DebuggerContainer dc = new DebuggerContainer(); foreach (Vertex vtx in outsideVertices) { Point pnt = Point.Construct(); pnt.Location = vtx.Position; pnt.Symbol = PointSymbol.Circle; dc.Add(pnt, vtx.GetHashCode()); } #endif // alle Faces, die aufgesplitted werden müssen: Set <Face> splittedFaces = new Set <Face>(); foreach (Edge edge in splitedEdges.Keys) { splittedFaces.Add(edge.PrimaryFace); if (edge.SecondaryFace != null) { splittedFaces.Add(edge.SecondaryFace); } } resultingFaces = new List <Face>(); for (int i = 0; i < shell.Faces.Length; i++) { Face face = shell.Faces[i]; if (splittedFaces.Contains(face)) { AddSplittedFace(face); } else { if (!outsideVertices.Contains(face.Vertices[0])) { resultingFaces.Add(face.Clone() as Face); } } } GeoObjectList res = Make3D.SewFacesAndShells(new GeoObjectList(resultingFaces.ToArray())); if (res.Count == 1) { return(res[0] as Shell); } return(null); }
public override ICurve2D GetFused(ICurve2D toFuseWith, double precision) { if (toFuseWith is Line2D) { toFuseWith = new Polyline2D(new GeoPoint2D[] { toFuseWith.StartPoint, toFuseWith.EndPoint }); } if (toFuseWith is Polyline2D) { Polyline2D pl1, pl2; if (length < toFuseWith.Length) { pl1 = toFuseWith.Clone() as Polyline2D; // 1. die längere pl2 = this.Clone() as Polyline2D; } else { pl1 = this.Clone() as Polyline2D; pl2 = toFuseWith.Clone() as Polyline2D; } // die kürzere muss wenigstens start oder endpunkt auf der längeren haben double pos1 = pl1.PositionOf(pl2.StartPoint); double pos2 = pl1.PositionOf(pl2.EndPoint); bool pos1inside = false; bool pos2inside = false; if (pos1 >= 0.0 && pos1 <= 1.0) { // Startpunkt liegt drauf if (Math.Abs(pl1.Distance(pl2.StartPoint)) < precision) { pos1inside = true; } } if (pos2 >= 0.0 && pos2 <= 1.0) { // Startpunkt liegt drauf if (Math.Abs(pl1.Distance(pl2.EndPoint)) < precision) { pos2inside = true; } } GeoPoint2D split1 = GeoPoint2D.Origin, split2 = GeoPoint2D.Origin; bool split = false; if (pos1inside && pos2inside) { bool ok = true; for (int i = 0; i < pl2.VertexCount; i++) { if (Math.Abs(pl1.Distance(pl2.vertex[i])) > precision) { ok = false; } } if (ok) { return(pl1); // die ist es bereits, und es ist ja auch ein clone } else { return(null); // zu großer Abstand } } else if (pos2inside) { // der Endpunkt von pl2 liegt innerhalb, der Startpunkt außerhalb double p = pl2.PositionOf(pl1.StartPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.StartPoint)) < precision) { // fängt an mit pl2, endet mid pl1, beide schon richtige Richtung split1 = pl1.StartPoint; split2 = pl2.EndPoint; split = true; Polyline2D tmp = pl2; pl2 = pl1; pl1 = tmp; } } if (!split) { p = pl2.PositionOf(pl1.EndPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.EndPoint)) < precision) { // fängt an mit pl2, endet mid pl1, pl1 muss umgedreht werden split1 = pl1.EndPoint; split2 = pl2.EndPoint; split = true; pl1.Reverse(); Polyline2D tmp = pl2; pl2 = pl1; pl1 = tmp; } } } } else if (pos1inside) { // der Startpunkt von pl2 liegt innerhalb, der Endpunkt außerhalb double p = pl2.PositionOf(pl1.StartPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.StartPoint)) < precision) { // fängt an mit pl1, endet mid pl2, pl1 falschrum split1 = pl2.StartPoint; split2 = pl1.StartPoint; split = true; pl1.Reverse(); } } if (!split) { p = pl2.PositionOf(pl1.EndPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.EndPoint)) < precision) { // fängt an mit pl1, endet mid pl2, beide richtigrum split1 = pl2.StartPoint; split2 = pl1.EndPoint; split = true; } } } } if (split) { // sie überlappen sich, das kann im Extramfall acuh einfach zusammenhängend sein #if DEBUG DebuggerContainer dc = new DebuggerContainer(); dc.Add(pl1, Color.Red, 1); dc.Add(pl2, Color.Green, 2); dc.Add(split1, Color.Red, 3); dc.Add(split2, Color.Blue, 4); #endif // if (pl1.ConnectWith(pl2, precision)) return pl1; // damit ist das schon erledigt, sonst gibt es beim Splitten einen Fehler // das macht Probleme bei zwei fast identischichen Polylines, die werden sonst in Gegenrichtung miteinander verbunden ICurve2D[] spl1 = pl1.Split(pl1.PositionOf(split1)); ICurve2D[] spl2 = pl2.Split(pl2.PositionOf(split2)); // Der Anfang von spl1 und das Ende von spl2 sind die Endstücke, das Mittelteil ist doppelt und muss identisch sein if (spl1.Length == 2 && spl2.Length == 2) { Polyline2D m1 = spl1[1] as Polyline2D; Polyline2D m2 = spl2[0] as Polyline2D; bool ok = true; for (int i = 0; i < m1.VertexCount; i++) { if (Math.Abs(m2.Distance(m1.vertex[i])) > precision) { ok = false; } } if (!ok) { return(null); } List <GeoPoint2D> pnts = new List <GeoPoint2D>((spl1[0] as Polyline2D).Vertex); for (int i = 1; i < m2.VertexCount; i++) { pnts.Add(m2.vertex[i]); } m2 = spl2[1] as Polyline2D; for (int i = 1; i < m2.VertexCount; i++) { pnts.Add(m2.vertex[i]); } return(new Polyline2D(pnts.ToArray())); } } } return(null); }