コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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
            //{
            //}
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }