コード例 #1
0
        internal double SpaceFunction(Point2d p, AM_Mesh2d pSpaceFunction)
        {
            if (pSpaceFunction != null)
            {
                double z = 0;
                if (pSpaceFunction.GetCoordZ(p, ref z))
                {
                    return(z);
                }
            }

            Point2d p0 = Vertex(0).Coord;
            Point2d p1 = Vertex(1).Coord;
            Point2d p2 = Vertex(2).Coord;

            double det = AM_Util.TriArea(p0, p1, p2);

            Debug.Assert(det != 0);
            double alfa = AM_Util.TriArea(p0, p, p2) / det;
            double beta = AM_Util.TriArea(p0, p1, p) / det;

            double f0 = Vertex(0).Space;
            double f1 = Vertex(1).Space;
            double f2 = Vertex(2).Space;

            double f = f0 + alfa * (f1 - f0) + beta * (f2 - f0);

            return(f);
        }
コード例 #2
0
        internal void ComputeCircumCircle()
        {
            Point2d P1 = Vertex(0).Coord,
                    P2 = Vertex(1).Coord,
                    P3 = Vertex(2).Coord;

            AM_Util.CircumCircle(P1, P2, P3, ref m_CircumCenter, ref m_CircumRadius);
        }
コード例 #3
0
        internal bool InsertVertex(AM_Mesh2d mesh, Point3d pt, int numGenVertex = 0)
        {
            while (numGenVertex < m_GenVertexArray.Count)
            {
                int v1 = m_GenVertexArray[numGenVertex];
                int v2 = m_GenVertexArray[(numGenVertex + 1) % m_GenVertexArray.Count];

                if (v2 < v1)
                {
                    v2 += m_GenVertexArray.Count;
                }

                Point2d p  = new Point2d(pt);
                Point2d p1 = new Point2d(m_ArrayCoord[v1]);
                Point2d p2 = new Point2d(m_ArrayCoord[v2]);

                Vector2d vec1 = (p2 - p1);
                Vector2d vec2 = (p - p1);

                vec1.Unitize();
                vec2.Unitize();

                if (AM_Util.IsEqual(vec2.Length, 0))
                {
                    double t = (p - p1).Length;
                    for (int i = v1 + 1; i <= v2; i++)
                    {
                        Point2d pv = new Point2d(m_ArrayCoord[i % m_ArrayCoord.Count]);
                        if ((pv - p1).Length > t)
                        {
                            AM_Vertex pVertex = null;
                            if (mesh.InsertPoint(p, pt.Z, out pVertex))
                            {
                                InsertVertex(i, pVertex);
                                return(true);
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }
                }

                numGenVertex++;
            }

            return(false);
        }
コード例 #4
0
ファイル: AM_Mesh2d.cs プロジェクト: cbing66/ReteStrutturata
        internal bool GetCoordZ(Point2d p, ref double Z)
        {
            // Localizza uno spigolo vicino
            AM_Edge edge = Locate(p);

            if (edge == null)
            {
                return(false);
            }

            AM_Face face = null;

            if (AM_Edge.LeftOf(p, edge))
            {
                face = edge.CcwFace();
            }
            else
            {
                face = edge.CwFace();
            }

            Z = 0;
            if (face == null)
            {
                return(false);
            }

            Point2d p0 = face.Vertex(0).Coord;
            Point2d p1 = face.Vertex(1).Coord;
            Point2d p2 = face.Vertex(2).Coord;

            double det = AM_Util.TriArea(p0, p1, p2);

            Debug.Assert(det != 00);
            double alfa = AM_Util.TriArea(p0, p, p2) / det;
            double beta = AM_Util.TriArea(p0, p1, p) / det;

            double f0 = face.Vertex(0).Z;
            double f1 = face.Vertex(1).Z;
            double f2 = face.Vertex(2).Z;

            Z = f0 + alfa * (f1 - f0) + beta * (f2 - f0);

            return(true);
        }
コード例 #5
0
ファイル: AM_Mesh2d.cs プロジェクト: cbing66/ReteStrutturata
        internal bool CheckWEdge()
        {
            for (int i = 0; i < m_ArrayWEdges.Count; i++)
            {
                AM_Edge edge = m_ArrayWEdges[i].Edge();
                Debug.Assert(edge.Origin() != edge.Destination());
            }

            for (int i = 0; i < m_ArrayFaces.Count; i++)
            {
                AM_Face edge = m_ArrayFaces[i];
                double  area = AM_Util.TriArea(edge[0].OrgCoord(),
                                               edge[1].OrgCoord(),
                                               edge[2].OrgCoord());
                Debug.Assert(area > 0);
            }

            return(true);
        }
コード例 #6
0
ファイル: AM_Region.cs プロジェクト: cbing66/ReteStrutturata
        bool BuildMeshBoundary(ref BoundingBox maxRect)
        {
            maxRect = BoundingBox.Empty;

            for (int i = 0; i < m_Loops.Count; i++)
            {
                var pLoop = m_Loops[i];

                AM_Boundary boundary = new AM_Boundary();
                m_ArrayMeshBoundary.Add(boundary);

                boundary.SetLoopIndex(i);
                boundary.FlagHole = m_Loops[i].IsClosed;

                for (int j = 0; j < pLoop.NumSegments; j++)
                {
                    var pVertex = pLoop.GetVertex(j);

                    boundary.AddPoint(pVertex.Location, pVertex.Space, true);
                    maxRect.Union(AM_Util.To3d(pVertex.Location));

                    var arrayPoints = pLoop.GetGeneratedPoints(j);

                    for (int k = 0; k < arrayPoints.Count; k++)
                    {
                        // Nota: questa riga serve per gestire l'orientamento
                        // TODO: valuatare se necessaria
                        //int n = (pEdge.m_Index & 0x01) ? (arrayPoint.size() - k - 1) : k;
                        int n      = k;
                        var meshPt = arrayPoints[k];

                        boundary.AddPoint(new Point2d(meshPt.X, meshPt.Y), meshPt.Z);
                        maxRect.Union(new Point3d(meshPt.X, meshPt.Y, 0));
                    }
                }
            }
            return(true);
        }
コード例 #7
0
        internal bool BuildVertexes(bool bForceEven)
        {
            int numSegments = NumSegments;

            for (int i = 0; i < numSegments; i++)
            {
                var crv = m_Curves[i];
                var pV1 = m_Vertexes[i];
                var pV2 = m_Vertexes[(i + 1) % m_Vertexes.Count];

                if (!IsClosed && i == numSegments - 1)
                {
                    pV2 = m_Vertexes[i + 1];
                }

                double space1 = pV1.Space;
                double space2 = pV2.Space;

                Point2d org  = pV1.Location;
                Point2d dest = pV2.Location;

                Point2d start = AM_Util.To2d(crv.PointAtStart);
                Point2d end   = AM_Util.To2d(crv.PointAtEnd);

                Debug.Assert(org.EpsilonEquals(start, AM_Util.FLT_EPSILON));
                Debug.Assert(dest.EpsilonEquals(end, AM_Util.FLT_EPSILON));

                m_GenPoint[i] = new List <Point4d>();

                if (!BuildPointFromSpace(bForceEven, org, dest, crv, space1, space2, m_GenPoint[i]))
                {
                }
            }

            return(true);
        }
コード例 #8
0
        internal bool RecoverGenEdge(AM_Mesh2d mesh, int num, List <Point3d> AddArray, bool bStraight = false)
        {
            // se viene inserito un punto per aggiustare la conformità
            // il flag baddFlag diventa true
            bool baddFlag = false;

            if (!m_bFlagHole && num >= m_GenVertexArray.Count)
            {
                return(true);
            }

            int v1 = m_GenVertexArray[num];
            int v2 = m_GenVertexArray[(num + 1) % m_GenVertexArray.Count];

            if (v2 < v1)
            {
                v2 += GetNumVertex();
            }

            AM_Edge pbase;
            AM_Edge pprev = pbase = Vertex(v1).Edge;

            for (int i = v1 + 1; i <= v2; i++)
            {
                AM_Vertex pV1 = Vertex((i - 1) % (GetNumVertex()));
                AM_Vertex pV2 = Vertex((i) % (GetNumVertex()));

                Point2d orgCoord = pV1.Coord;

                // si controlla che tutti i vertici siano in sequenza
                while (true)
                {
                    Point2d baseCoord = pbase.DestCoord();

                    Point2d prvCoord  = new Point2d(m_ArrayCoord[(i - 1) % (GetNumVertex())]);
                    Point2d destCoord = new Point2d(m_ArrayCoord[i % (GetNumVertex())]);

                    if (baseCoord == destCoord)
                    {
                        // il vertice è in sequenza: si continua con il successivo
                        break;
                    }
                    else
                    {
                        pbase = pbase.Next;

                        if (pbase == pprev)
                        {
                            // il ciclo dell'anello si è chiuso senza trovare il vertice
                            // successivo; è necessario inserire un vertice in mezzeria del
                            // lato mancante

                            if (!bStraight)
                            {
                                // 1. Algoritmo di ripristino del bordo con l'aggiunta del punto medio
                                baddFlag = true; // si segnala l'aggiunta di un vertice

                                Point3d p1    = m_ArrayCoord[i - 1];
                                Point3d p2    = (m_ArrayCoord[i % (GetNumVertex())]);
                                Point3d mid   = 0.5 * (p1 + p2);
                                Point3d insPt = new Point3d(mid.X, mid.Y, 0);

                                // si inserisce un vertice nel mezzo del
                                AM_Vertex pvertex;
                                mesh.InsertPoint(new Point2d(insPt), insPt.Z, out pvertex);

                                if (pvertex == null)
                                {
                                    Debug.Assert(false);
                                    //throw 6;
                                }


                                InsertVertex(i, pvertex);
                                v2++;
                                AddArray.Add(insPt);

                                // si ricomincia il controllo
                                pbase = Vertex(i - 1).Edge;
                                pprev = pbase;
                            }
                            else
                            {
                                // 2. Algoritmo di ripristino del bordo con swap di spigoli
                                AM_Edge pdest = Vertex(i).Edge;

                                Vector2d dir = destCoord - orgCoord;
                                dir.Unitize();

                                var m = AM_Util.AffineMatrix(orgCoord, dir);

                                while (pV1.FindEdge(pV2) == null)
                                {
                                    bool    bCoinc  = false;
                                    AM_Edge pSearch = pbase;

                                    // Si controllano situazioni di appartenenza al lato da ripristinare
                                    do
                                    {
                                        double cosang = Vector2d.Multiply(pSearch.GetVersor(), dir);

                                        if (AM_Util.IsEqual(cosang, 1, AM_Util.FLT_EPSILON))
                                        {
                                            // Lo spigolo appartiene già al lato da ripristinare
                                            InsertVertex(i, pSearch.Destination());
                                            v2++;

                                            Point2d dc = pSearch.DestCoord();
                                            AddArray.Add(new Point3d(dc.X, dc.Y, 0));

                                            // si ricomincia il controllo
                                            pbase = Vertex(i - 1).Edge;
                                            pprev = pbase;

                                            bCoinc = true;
                                            break;
                                        }
                                        pSearch = pSearch.Next;
                                    } while (pSearch != pbase);

                                    if (bCoinc)
                                    {
                                        break;
                                    }

                                    // Trova il lato di partenza
                                    pSearch = pbase;

                                    while (!AM_Util.IsInside(pSearch.GetVector(), pSearch.Next.GetVector(), dir))
                                    {
                                        pSearch = pSearch.Next;
                                        if (pSearch == pprev)
                                        {
                                            Debug.Assert(false);
                                            //mesh.ExportMesh("RecoverSt7.txt");
                                            return(false);
                                        }
                                    }

                                    AM_Edge        pStartEdge = pSearch.CcwEdge();
                                    List <AM_Edge> swapArray  = new List <AM_Edge>();

                                    while (pStartEdge.Destination() != pV2)
                                    {
                                        Point2d o = pStartEdge.OrgCoord();
                                        Point2d d = pStartEdge.DestCoord();
                                        swapArray.Add(pStartEdge);

                                        pStartEdge = pStartEdge.Prev;
                                        Point2d pt = AM_Util.ToLocal(m, pStartEdge.DestCoord());
                                        if (pt.Y < -AM_Util.FLT_EPSILON)
                                        {
                                            pStartEdge = pStartEdge.CcwEdge();

                                            Debug.Assert(AM_Util.ToLocal(m, pStartEdge.DestCoord()).Y > 0);
                                        }
                                    }

                                    for (int j = 0; j < swapArray.Count; j++)
                                    {
                                        AM_Edge pSwapEdge = swapArray[j];

                                        // Vengono ruotati gli spigoli all'interno
                                        if (AM_Util.CheckSwapEdge(pSwapEdge))
                                        {
                                            Debug.Assert(pSearch.CcwFace() != null && pSearch.Next.CwFace() != null);
                                            Debug.Assert(pSwapEdge.CcwFace() != null && pSwapEdge.CwFace() != null);

                                            AM_Face.SwapEdge(pSwapEdge);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                pbase = Vertex(i % (GetNumVertex())).Edge;
                pprev = pbase;
            }

            return(baddFlag);
        }
コード例 #9
0
        // --- Copia ---
        AM_Boundary CopyBoundary(AM_Mesh2d source, AM_Mesh2d dest,
                                 bool bSameGenVertex = true)
        {
            AM_Boundary pCopy = new AM_Boundary();

            pCopy.m_LoopIndex = m_LoopIndex;

            if (bSameGenVertex)
            {
                // Il numero dei vertici generati è lo stesso;
                // viene normalmente usato in caso di 'merge' tra due mesh adiacenti
                pCopy.m_ArrayCoord.Capacity = m_ArrayCoord.Count;
                for (int i = 0; i < m_ArrayCoord.Count; i++)
                {
                    pCopy.m_ArrayCoord[i] = m_ArrayCoord[i];
                }

                pCopy.m_GenVertexArray.Capacity = m_GenVertexArray.Count;
                for (int i = 0; i < m_GenVertexArray.Count; i++)
                {
                    pCopy.m_GenVertexArray[i] = m_GenVertexArray[i];
                }

                // Trova il primo vertice
                int destVertex = dest.ArrayVertexes.Count;
                int nVertex    = dest.AddVertex(new Point2d(m_ArrayCoord[0]), m_ArrayCoord[0].Z);
                Debug.Assert(nVertex < destVertex); // non vengono aggiunti vertici

                AM_Vertex pVertex = dest.ArrayVertexes[nVertex];
                pVertex.Flag |= 0x01;
                pCopy.m_ArrayVertex.Add(pVertex);

                for (int i = 1; i < m_ArrayCoord.Count; i++)
                {
                    Point2d ptDest    = new Point2d(m_ArrayCoord[i]);
                    AM_Edge pEdge     = pVertex.Edge;
                    AM_Edge pNextEdge = pEdge.Next;

                    while ((ptDest - pNextEdge.DestCoord()).Length > AM_Util.FLT_EPSILON)
                    {
                        if (pNextEdge == pEdge)
                        {
                            Debug.Assert(false);
                            nVertex = dest.AddVertex(ptDest, 0);
                            Debug.Assert(nVertex < destVertex);
                            pNextEdge = dest.ArrayVertexes[nVertex].Edge.Symm();
                            break;
                        }
                        pNextEdge = pNextEdge.Next;
                    }

                    pVertex       = pNextEdge.Destination();
                    pVertex.Flag |= 0x01;
                    pCopy.m_ArrayVertex.Add(pVertex);
                }

                Debug.Assert(pCopy.m_ArrayVertex.Count == m_ArrayVertex.Count);
            }
            else
            {
                // Il numero dei vertici generati è diverso;
                // viene normalmente usato in caso di ricostruzione di contorni
                pCopy.m_GenVertexArray.Capacity = m_GenVertexArray.Count;

                for (int i = 1; i < m_GenVertexArray.Count; i++)
                {
                    Point2d p0 = new Point2d(m_ArrayCoord[m_GenVertexArray[i - 1]]);
                    Point2d p1 = new Point2d(m_ArrayCoord[m_GenVertexArray[i]]);

                    AM_Vertex pV0 = dest.RangeSearch.Search(p0.X, p0.Y);
                    AM_Vertex pV1 = dest.RangeSearch.Search(p1.X, p1.Y);
                    Debug.Assert(pV0 != null && pV1 != null);

                    // La direzione è data dal vettore p0-p1
                    Vector2d vDir = (p1 - p0);
                    vDir.Unitize();

                    pCopy.m_GenVertexArray[i - 1] = pCopy.m_ArrayCoord.Count;

                    AM_Vertex pV = pV0;
                    while (pV != pV1)
                    {
                        pCopy.m_ArrayCoord.Add(new Point3d(pV.Coord.X, pV.Coord.Y, 0));
                        pCopy.m_ArrayVertex.Add(pV);

                        // Trova il vertice successivo
                        double minCos = -double.MaxValue;

                        AM_Edge pEdge    = pV.Edge;
                        AM_Edge pDirEdge = null;

                        do
                        {
                            double dirCos = pEdge.GetVersor() * vDir;
                            if (dirCos > minCos)
                            {
                                minCos   = dirCos;
                                pDirEdge = pEdge;
                            }

                            pEdge = pEdge.Next;
                        } while (pEdge != pV.Edge);

                        Debug.Assert(AM_Util.IsEqual(minCos, 1));
                        pV = pDirEdge.Destination();
                    }
                }
            }

            return(pCopy);
        }
コード例 #10
0
        bool BuildPointFromSpace(bool bForceEven, Point2d org, Point2d dest, Curve crv,
                                 double space1, double space2, List <Point4d> GenPoint)
        {
            GenPoint.Clear();

            double len    = crv.GetLength();
            var    domain = crv.Domain;

            double step  = (space1 + space2) / 2;
            double dStep = space2 - space1;

            if (dStep > 0)
            {
                double h1 = space1;
                double h2 = space2;

                Debug.Assert(h1 != 0 && h2 != 0); // la spaziatura non deve essere nulla

                double r        = (len - h1) / (len - h2);
                double k        = Math.Log(h2 / h1) / Math.Log(r);
                double kk       = 0;
                int    numJoint = AM_Util.IntNear(k);
                if (numJoint != 0)
                {
                    kk = Math.Log(r * h2 / h1) / Math.Log(r) / (numJoint + 1);
                }
                else
                {
                    return(false);
                }

                Debug.Assert(!bForceEven);

                for (int j = 0; j < numJoint; j++)
                {
                    double partialLen = h1 * (Math.Pow(r, kk * (j + 1)) - 1) / (r - 1);

                    double percent = partialLen / len;
                    double space   = h1 + (h2 - h1) * percent;

                    double t = percent;
                    Debug.Assert(t > 0 && t < 1);

                    double  par      = (percent * domain.Length);
                    Point2d newCoord = AM_Util.To2d(crv.PointAt(par));

                    GenPoint.Add(new Point4d(newCoord.X, newCoord.Y, space, t));
                }
            }
            else
            {
                int n = (int)(len / step);

                if (bForceEven)
                {
                    n *= 2;
                    if (n == 0)
                    {
                        n = 2;
                    }
                }

                if (n != 0)
                {
                    for (int k = 1; k < n; k++)
                    {
                        double t     = (double)(k) / (double)(n);
                        double space = len / n;

                        double  par      = (t * domain.Length);
                        Point2d newCoord = AM_Util.To2d(crv.PointAt(domain.Min + par));

                        GenPoint.Add(new Point4d(newCoord.X, newCoord.Y, space, t));
                    }
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #11
0
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            var ptPuffynessOption       = new OptionToggle(m_PointPuffyness, "False", "True");
            var ptOffsetOption          = new OptionDouble(m_PuffynessOffset, 0.5, double.PositiveInfinity);
            var ptBorderPuffynessOption = new OptionToggle(m_BorderPuffyness, "False", "True");
            var borderOffsetOption      = new OptionDouble(m_BorderOffset, 0.5, double.PositiveInfinity);

            var go = new GetOption();

            go.SetCommandPrompt("Get meshing properties");
            go.AcceptNothing(true);
            go.AcceptEnterWhenDone(true);

            int ptPuffyOptionIndex      = go.AddOptionToggle("PointPuffyness", ref ptPuffynessOption);
            int offsetOptionIndex       = go.AddOptionDouble("OffsetPtPuffy", ref ptOffsetOption);
            int borderPuffyOptionIndex  = go.AddOptionToggle("BorderPuffyness", ref ptBorderPuffynessOption);
            int borderOffsetOptionIndex = go.AddOptionDouble("OffsetBorderPuffy", ref borderOffsetOption);

            go.Get();
            var result = go.Result();

            while (result != GetResult.Nothing)
            {
                if (result == GetResult.Cancel)
                {
                    return(Result.Cancel);
                }

                int optionIdx = go.OptionIndex();
                if (optionIdx == ptPuffyOptionIndex)
                {
                    m_PointPuffyness = ptPuffynessOption.CurrentValue;
                }
                else if (optionIdx == offsetOptionIndex)
                {
                    m_PuffynessOffset = ptOffsetOption.CurrentValue;
                }
                else if (optionIdx == borderPuffyOptionIndex)
                {
                    m_BorderPuffyness = ptBorderPuffynessOption.CurrentValue;
                }
                else if (optionIdx == borderOffsetOptionIndex)
                {
                    m_BorderOffset = borderOffsetOption.CurrentValue;
                }

                result = go.Get();
            }

            ObjRef[] rhObjects;
            var      res = RhinoGet.GetMultipleObjects("Select planar curves and Weight points", false, Rhino.DocObjects.ObjectType.Curve | Rhino.DocObjects.ObjectType.Point, out rhObjects);

            if (res == Result.Success)
            {
                // 1. subdive in sets: Closed curves, Opened Curves, weight points;
                List <Curve> closed_crvs   = new List <Curve>();
                List <Curve> opened_crvs   = new List <Curve>();
                List <Point> weight_points = new List <Point>();

                bool   puffyness = m_PointPuffyness;
                double offset    = m_PuffynessOffset;

                bool   border_puffyness = m_BorderPuffyness;
                double border_offset    = m_BorderOffset;

                foreach (var ref_obj in rhObjects)
                {
                    RhinoObject obj = ref_obj.Object();
                    if (obj.Geometry is Curve)
                    {
                        var crv = obj.Geometry as Curve;
                        if (crv.IsPlanar())
                        {
                            if (crv.IsClosed)
                            {
                                closed_crvs.Add(crv);
                            }
                            else
                            {
                                opened_crvs.Add(crv);
                            }
                        }
                    }
                    else if (obj.Geometry is Point)
                    {
                        weight_points.Add(obj.Geometry as Point);
                    }
                }

                double space = 1;

                // 2. Insert curves into mesh
                AM_Region region = null;

                Curve border_outer_crv = null;
                Curve offset_outer_crv = null;

                if (closed_crvs.Count > 0)
                {
                    region = new AM_Region();

                    for (int i = 0; i < closed_crvs.Count; i++)
                    {
                        var crv = closed_crvs[i];

                        region.AddCurve(crv, space, false);

                        AreaMassProperties area = AreaMassProperties.Compute(crv, AM_Util.FLT_EPSILON);
                        if (area.Area > 0 && border_puffyness)
                        {
                            if (border_outer_crv == null)
                            {
                                border_outer_crv = crv;
                            }

                            var offset_Crvs = crv.Offset(Plane.WorldXY, -border_offset, AM_Util.FLT_EPSILON, CurveOffsetCornerStyle.None);

                            foreach (var c in offset_Crvs)
                            {
                                c.Reverse();
                                doc.Objects.AddCurve(c);
                                offset_outer_crv = c;

                                region.AddCurve(c, space, true);
                            }
                        }
                    }
                }
                else
                {
                    // TODO
                    Debug.Assert(false);
                    return(Result.Failure);
                }

                for (int i = 0; i < weight_points.Count; i++)
                {
                    var pt = weight_points[i];

                    region.AddWeigthPoint(pt, space / 2);
                    if (puffyness && offset > 0)
                    {
                        var circle = new ArcCurve(new Circle(pt.Location, offset));
                        var nurbs  = circle.ToNurbsCurve();
                        region.AddCurve(nurbs, space / 2, true);
                    }
                }

                for (int i = 0; i < opened_crvs.Count; i++)
                {
                    var crv = opened_crvs[i];
                    region.AddCurve(crv, space, false);

                    if (puffyness && offset > 0)
                    {
                        var     n         = Vector3d.CrossProduct(crv.TangentAtStart, Vector3d.ZAxis);
                        Curve[] offsetCrv = crv.Offset(crv.PointAtStart + offset * n, Vector3d.ZAxis, offset, AM_Util.FLT_EPSILON, CurveOffsetCornerStyle.Round);

                        foreach (var c in offsetCrv)
                        {
                            doc.Objects.AddCurve(c);
                            region.AddCurve(crv, space, false);
                        }

                        Curve[] offsetCrv2 = crv.Offset(crv.PointAtStart - offset * n, Vector3d.ZAxis, offset, AM_Util.FLT_EPSILON, CurveOffsetCornerStyle.Round);

                        foreach (var c in offsetCrv2)
                        {
                            doc.Objects.AddCurve(c);
                            region.AddCurve(crv, space, false);
                        }
                    }
                }

                // 3. Mesh della regione
                if (region != null)
                {
                    if (region.BuildMesh())
                    {
                        // Inserisce i punti del contorno
                        foreach (var loop in region.Loops)
                        {
                            for (int i = 0; i < loop.NumSegments; i++)
                            {
                                var points = loop.GetGeneratedPoints(i);

                                //if (points != null) {
                                //  foreach (var p in points) {
                                //    doc.Objects.AddPoint(new Point3d(p.X, p.Y, 0));
                                //  }
                                //}
                            }
                        }
                    }

                    // Trasforma in Mesh di Rhino
                    var mesh = region.Mesh2D;

                    if (mesh != null)
                    {
                        Mesh   rhino_mesh = new Mesh();
                        double t          = 5;
                        for (int i = 0; i < mesh.ArrayVertexes.Count; i++)
                        {
                            mesh.ArrayVertexes[i].Z = t;
                        }

                        // PostProcessa il puffyness
                        if (puffyness)
                        {
                            for (int i = 0; i < region.ArrayInnerVertex.Count; i++)
                            {
                                var iv = region.ArrayInnerVertex[i];
                                if (iv.MeshVertex != null)
                                {
                                    iv.MeshVertex.Z = (4 / 5d) * t;
                                }

                                // Ricerca i punti nell'intorno fino all'offset (molto grezza!)
                                for (int j = 0; j < mesh.ArrayVertexes.Count; j++)
                                {
                                    var    v = mesh.ArrayVertexes[j];
                                    double d = (iv.MeshVertex.Coord - v.Coord).Length;
                                    if (d < offset)
                                    {
                                        double r = d / offset;

                                        AM_Util.EInterpolation interpolation = AM_Util.EInterpolation.Parabolic;
                                        v.Z = AM_Util.Interpolation(interpolation, iv.MeshVertex.Z, t, r);
                                    }
                                }
                            }
                        }

                        // Individua i punti all'interno della zona di transizione
                        List <int> transitionVts = new List <int>();

                        if (border_puffyness && border_offset > 0)
                        {
                            // Individua i vertici di partenza e utilizza u flag di lavoro
                            List <AM_Vertex> transitionStartVts = new List <AM_Vertex>();

                            for (int i = 0; i < mesh.ArrayVertexes.Count; i++)
                            {
                                var  v = mesh.ArrayVertexes[i];
                                bool is_loop_vertex = (v.Flag & 0x1) > 0;
                                v.Flag &= ~0x02;

                                if (is_loop_vertex && BelongToBorder(v))
                                {
                                    transitionStartVts.Add(v);
                                }
                            }

                            // Si usa 0x04 come flag di lavoro
                            for (int i = 0; i < mesh.ArrayWEdges.Count; i++)
                            {
                                var e                 = mesh.ArrayWEdges[i];
                                e.Edge().Flag        &= ~0x04;
                                e.Edge().Symm().Flag &= ~0x04;
                            }

                            for (int i = 0; i < transitionStartVts.Count; i++)
                            {
                                var v = transitionStartVts[i];
                                AddTransitionVertexes(v, transitionVts);
                            }

                            if (offset_outer_crv != null)
                            {
                                foreach (var iv in transitionVts)
                                {
                                    var v = mesh.ArrayVertexes[iv];

                                    double par;
                                    if (offset_outer_crv.ClosestPoint(AM_Util.To3d(v.Coord), out par, 2 * border_offset))
                                    {
                                        Point3d cp = offset_outer_crv.PointAt(par);
                                        double  r  = ((cp - AM_Util.To3d(v.Coord)).Length) / border_offset;
                                        double  z  = AM_Util.Interpolation(AM_Util.EInterpolation.Parabolic, 0.8 * t, t, 1 - r);
                                        v.Z = z;
                                    }
                                }
                            }
                        }

                        // Facce
                        int totVtx = mesh.ArrayVertexes.Count;

                        for (int iSide = 0; iSide < 2; iSide++)
                        {
                            for (int i = 0; i < mesh.ArrayVertexes.Count; i++)
                            {
                                var     v  = mesh.ArrayVertexes[i];
                                Point3d pt = v.Coord3d;
                                if (iSide == 1)
                                {
                                    pt.Z = 0;
                                }

                                rhino_mesh.Vertices.Add(pt);
                            }

                            for (int i = 0; i < mesh.ArrayFaces.Count; i++)
                            {
                                var f = mesh.ArrayFaces[i];

                                int numEdges = f.NumEdges;
                                if (numEdges == 3)
                                {
                                    int[] vtx = { f.Vertex(0).Index, f.Vertex(1).Index, f.Vertex(2).Index };
                                    if (iSide == 1)
                                    {
                                        vtx = new int[] { f.Vertex(0).Index + totVtx, f.Vertex(2).Index + totVtx, f.Vertex(1).Index + totVtx };
                                    }
                                    rhino_mesh.Faces.AddFace(vtx[0], vtx[1], vtx[2]);
                                }
                                else if (numEdges == 4)
                                {
                                    int[] vtx = { f.Vertex(0).Index, f.Vertex(1).Index, f.Vertex(2).Index, f.Vertex(3).Index };
                                    if (iSide == 1)
                                    {
                                        vtx = new int[] { f.Vertex(0).Index + totVtx, f.Vertex(3).Index + totVtx, f.Vertex(2).Index + totVtx, f.Vertex(1).Index + totVtx };
                                    }

                                    rhino_mesh.Faces.AddFace(vtx[0], vtx[1], vtx[2], vtx[3]);
                                }
                            }
                        }

                        for (int iEdge = 0; iEdge < mesh.ArrayWEdges.Count; iEdge++)
                        {
                            var edge = mesh.ArrayWEdges[iEdge].Edge();
                            if (edge.CcwFace() == null || edge.CwFace() == null)
                            {
                                // E' uno spigolo di bordo
                                int[] vtx = { edge.Destination().Index,     edge.Origin().Index,
                                              edge.Origin().Index + totVtx, edge.Destination().Index + totVtx, };
                                rhino_mesh.Faces.AddFace(vtx[0], vtx[1], vtx[2], vtx[3]);
                            }
                        }

                        rhino_mesh.Normals.ComputeNormals();
                        rhino_mesh.Compact();
                        if (doc.Objects.AddMesh(rhino_mesh) != Guid.Empty)
                        {
                            doc.Views.Redraw();
                            return(Rhino.Commands.Result.Success);
                        }
                    }
                }

                return(Result.Success);
            }


            return(Result.Cancel);
        }
コード例 #12
0
ファイル: AM_Region.cs プロジェクト: cbing66/ReteStrutturata
        internal void AddWeigthPoint(Point pt, double space)
        {
            var mv = new AM_RegionVertex(AM_Util.To2d(pt.Location), space);

            m_ArrayInnerVertex.Add(mv);
        }
コード例 #13
0
 internal static bool LeftOf(Point2d x, AM_Edge pedge)
 {
     return(AM_Util.CCW(x, pedge.OrgCoord(), pedge.DestCoord()));
 }
コード例 #14
0
ファイル: AM_Mesh2d.cs プロジェクト: cbing66/ReteStrutturata
        internal bool InsertPoint(Point2d x, double space, out AM_Vertex pvertex)
        {
            pvertex = null;
            AM_Face face = null;

            // Localizza uno spigolo vicino
            AM_Edge edge = Locate(x);

            if (edge == null)
            {
                return(false);
            }

            // Localizza il triangolo che contiene il punto x
            // e imposta 'm_pStartingEdge', primo spigolo del triangolo o del quadrilatero
            // che deve essere riconnesso al punto x
            if (AM_Edge.LeftOf(x, edge))
            {
                face           = (AM_Face)(edge.CcwFace());
                m_StartingEdge = edge.CcwEdge();
            }
            else
            {
                face           = (AM_Face)(edge.CwFace());
                m_StartingEdge = edge.Symm().CcwEdge();
            }

            if (face == null)
            {
                return(false);
            }

            // Verifica dell'eventuale esistenza del punto
            if (x == edge.OrgCoord())
            {
                pvertex = edge.Origin();
                return(false);
            }

            if (x == edge.DestCoord())
            {
                pvertex = edge.Destination();
                return(false);
            }

            Point2d[] v1 = { face.Vertex(0).Coord, face.Vertex(1).Coord, face.Vertex(2).Coord, };

            //isOnEdge = OnEdge(x, edge);
            AM_Edge pOnEdge = OnFaceEdge(x, face);

            if (pOnEdge != null)
            {
                m_StartingEdge = pOnEdge.CcwEdge();

                // il punto si trova su un contorno!
                AM_Face pCwFace  = pOnEdge.CwFace();
                AM_Face pCcwFace = pOnEdge.CcwFace();

                if (pCwFace == null || pCcwFace == null)
                {
                    return(false);
                }
            }

            // Il punto è all'interno di un triangolo o su uno spigolo
            if (face.FaceType == AM_Face.EFaceType.FT_ACTIVE)
            {
                DeleteActiveFace(face);
            }

            DeleteFace(face);
            if (pOnEdge != null)
            {
                // Cancella lo spigolo su cui si appoggia e
                // conseguentemente anche l'altro spigolo

                AM_Face pCwFace  = pOnEdge.CwFace();
                AM_Face pCcwFace = pOnEdge.CcwFace();

                if (pCwFace != null && pCwFace.FaceType == AM_Face.EFaceType.FT_ACTIVE)
                {
                    DeleteActiveFace(pCwFace);
                }
                if (pCcwFace != null && pCcwFace.FaceType == AM_Face.EFaceType.FT_ACTIVE)
                {
                    DeleteActiveFace(pCcwFace);
                }

                DeleteEdge(pOnEdge);
            }

            // Inserisce il nuovo vertice nell'array globale
            pvertex = new AM_Vertex(x, 0, space);
            if (pvertex == null)
            {
                Debug.Assert(false);
                //throw -1;
            }


            int m_nVertex = m_ArrayVertexes.Count;

            pvertex.Index = m_ArrayVertexes.Count;
            m_ArrayVertexes.Add(pvertex);

            // Inserisce i nuovi triangoli (facce)
            edge = m_StartingEdge.CcwEdge();
            int numEdge = (pOnEdge != null? 4 : 3);

            for (int ne = 0; ne < numEdge; ne++)
            {
                AM_Face new_face = new AM_Face();
                if (new_face == null)
                {
                    Debug.Assert(false);
                    //throw -1;
                }

                AM_Edge actEdge = edge;
                edge = edge.CcwEdge();
                int [] nCoord = { m_nVertex, actEdge.Vertex.Index, actEdge.DestVertex().Index };
                AddFace(new_face, nCoord);

                if (m_bFlagClassific)
                {
                    new_face.SetTriangleParameter(m_pSpaceFunction);
                    Classific(new_face);
                }
            }

            // Esamina gli spigoli per assicurare che la condizione di
            // Delaunay sia soddisfatta
            edge           = m_StartingEdge;
            m_StartingEdge = m_StartingEdge.CcwEdge();
            do
            {
                //TRACE_EDGE(edge);
                AM_Edge t = edge.Prev;
                if (edge.CwFace() != null && AM_Edge.RightOf(t.DestCoord(), edge) &&
                    AM_Util.InCircle(edge.OrgCoord(), t.DestCoord(), edge.DestCoord(), x))
                {
                    //TRACE0("Faccia swap:  ");
                    //TRACE_EDGE(edge);
                    Swap(edge);
                    edge = edge.Prev;
                }
                else if (edge.Next == m_StartingEdge)
                {
                    // Non ci sono più spigoli
                    break;
                }
                else
                {
                    // Recupera un altro spigolo sospetto
                    edge = edge.Next.CwEdge();
                }
            } while (true);

            return(true);
        }
コード例 #15
0
ファイル: AM_Mesh2d.cs プロジェクト: cbing66/ReteStrutturata
        internal double SmoothMesh()
        {
            double eps = 0;

            for (int n = 0; n < m_NumSmoothing; n++) //ripeto Num volte lo smoothing
            {
                eps = 0;
                for (int i = 0; i < m_ArrayVertexes.Count; i++)
                {
                    // ciclo per tutti i punti interni al dominio
                    AM_Vertex vertex = m_ArrayVertexes[i];

                    // Versione corretta (AC 16-01-03)
                    // Algoritmo di Optimal Smoothing (Borouchaki-George IJNME vol.40)
                    if (vertex.Flag == 0) // E' un punto smoothabile
                    {
                        Point2d p0     = vertex.Coord;
                        Point2d center = Point2d.Unset;
                        int     degree = (int)vertex.Degree(true);
                        if (degree < 2)
                        {
                            continue;
                        }

                        AM_Edge start    = vertex.Edge;
                        AM_Edge nextEdge = start;

                        Point2d newCoord   = Point2d.Unset;
                        double  oldQuality = double.MaxValue;

                        // Valuta la qualità dei triangoli prima dello spostamento
                        // e calcola il nuovo centro
                        for (int j = 0; j < degree; j++)
                        {
                            Debug.Assert(nextEdge.CcwFace() != null);
                            Point2d p1 = nextEdge.DestCoord();
                            Point2d p2 = nextEdge.Next.DestCoord();

                            // Punto del teorico triangolo equilatero di p1-p2
                            Vector2d v  = p2 - p1;
                            Point2d  mp = 0.5 * (p1 + p2);
                            Point2d  np = mp + Math.Sqrt(3d) * v.Length * AM_Util.NormalVersor(v);

                            newCoord += np;

                            double inRadius     = 0;
                            double circumRadius = 0;

                            AM_Util.CircumCircle(p0, p1, p2, ref center, ref circumRadius);
                            AM_Util.InCircle(p0, p1, p2, ref center, ref inRadius);
                            double sgnArea = AM_Util.TriArea(p0, p1, p2) > 0 ? 1 : -1;

                            double quality = sgnArea * inRadius / circumRadius;
                            oldQuality = Math.Min(oldQuality, quality);

                            nextEdge = nextEdge.Next;
                        }
                        Debug.Assert(nextEdge == start);

                        newCoord.X /= degree;
                        newCoord.Y /= degree;

                        // Controlla l'accettabilità del nuovo centro
                        double newQuality = double.MaxValue;

                        for (int j = 0; j < degree; j++)
                        {
                            Debug.Assert(nextEdge.CcwFace() != null);
                            Point2d p1 = nextEdge.DestCoord();
                            Point2d p2 = nextEdge.Next.DestCoord();

                            double inRadius     = 0;
                            double circumRadius = 0;
                            AM_Util.CircumCircle(newCoord, p1, p2, ref center, ref circumRadius);
                            AM_Util.InCircle(newCoord, p1, p2, ref center, ref inRadius);
                            double sgnArea = AM_Util.TriArea(newCoord, p1, p2) > 0? 1 : -1;

                            double quality = sgnArea * inRadius / circumRadius;
                            newQuality = Math.Min(quality, newQuality);

                            nextEdge = nextEdge.Next;
                        }

                        Debug.Assert(nextEdge == start);

                        if (newQuality > 0 && newQuality > oldQuality)
                        {
                            // La qualità viene migliorata, il vertice viene spostato
                            eps         += (newCoord - p0).Length;
                            vertex.Coord = newCoord;
                        }
                    }
                }
            }

            return(eps);
        }