/// <summary>
 /// Search for duplicate edges?  Optimize using a hash
 /// </summary>
 /// <param name="indexA"></param>
 /// <param name="indexB"></param>
 /// <param name="classes"></param>
 /// <param name="verts"></param>
 public static void SetEdgeHash(int indexA, int indexB, ClassificationUtil.Classification[] classes, Vector3[] verts)
 {
     if (classes[indexA] == ClassificationUtil.Classification.COINCIDING && classes[indexB] == ClassificationUtil.Classification.COINCIDING)
     {
         if (!MeshSlicer.hashCheck.ContainsKey(verts[indexA] + verts[indexB]))
         {
             MeshSlicer.hashCheck.Add(verts[indexA] + verts[indexB], 0);
             MeshSlicer.debugEdges.Add(new Vector3[] { verts[indexA], verts[indexB] });
         }
     }
 }
        public void ShouldClassifySameImages()
        {
            Dictionary <string, double> img1 = new Dictionary <string, double>();

            img1.Add("1", 0.0);
            img1.Add("2", 0.0);
            img1.Add("3", 1.0);
            img1.Add("4", 1.0);

            Dictionary <string, double> img2 = new Dictionary <string, double>();

            img2.Add("1", 0.0);
            img2.Add("2", 0.0);
            img2.Add("3", 1.0);
            img2.Add("4", 1.0);

            Dictionary <string, double> img3 = new Dictionary <string, double>();

            img3.Add("1", 1.0);
            img3.Add("2", 1.0);
            img3.Add("3", 0.0);
            img3.Add("4", 0.0);

            Dictionary <string, double> img4 = new Dictionary <string, double>();

            img4.Add("1", 1.0);
            img4.Add("2", 1.0);
            img4.Add("3", 0.0);
            img4.Add("4", 0.0);

            Dictionary <string, Dictionary <string, double> > matrix = new Dictionary <string, Dictionary <string, double> >();

            matrix.Add("1", img1);
            matrix.Add("2", img2);
            matrix.Add("3", img3);
            matrix.Add("4", img4);

            List <List <string> > groups = ClassificationUtil.Classify(matrix, ClassificationMode.INNER, 2);

            Assert.AreEqual(2, groups.Count);
            foreach (var group in groups)
            {
                Assert.AreEqual(2, group.Count);
                Assert.IsTrue((group.Contains("1") && group.Contains("2")) ||
                              (group.Contains("3") && group.Contains("4")));
            }
        }
Esempio n. 3
0
        public List <int> Predict(List <List <int> > X)
        {
            var retVal = new List <int>();

            var doublesList = new List <List <double> >();

            foreach (var xi in X)
            {
                doublesList.Add(xi.Select(i => (double)i).ToList());
            }

            var distances = ClassificationUtil.EuclidianDistance(doublesList, _means);

            foreach (var distance in distances)
            {
                retVal.Add(distance.IndexOf(distance.Max()));
            }

            return(retVal);
        }
    public static void SetEdge(int indexA, int indexB, ClassificationUtil.Classification[] classes, Vector3[] points)
    {
        bool found = false;
        if (classes[indexA] == ClassificationUtil.Classification.COINCIDING && classes[indexB] == ClassificationUtil.Classification.COINCIDING)
        {
            foreach (Vector3[] edges in MeshSlicer.debugEdges)
            {
                if (edges[0] == points[indexA] && edges[1] == points[indexB] || edges[1] == points[indexA] && edges[0] == points[indexB])
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                MeshSlicer.debugEdges.Add(new Vector3[] { points[indexA], points[indexB] });
            }
        }
    }
    public static void SetEdge(int indexA, int indexB, ClassificationUtil.Classification[] classes, Triangle3D triangle)
    {
        bool found = false;
        if(classes[indexA] == ClassificationUtil.Classification.COINCIDING && classes[indexB] == ClassificationUtil.Classification.COINCIDING)
        {
            foreach(Vector3[] edges in MeshSlicer.debugEdges)
            {
                if(edges[0] == triangle.vertices[indexA].pos && edges[1] == triangle.vertices[indexB].pos || edges[1] == triangle.vertices[indexA].pos && edges[0] == triangle.vertices[indexB].pos)
                {
                    found = true;
                    break;
                }
            }

            if(!found)
            {
                MeshSlicer.debugEdges.Add(new Vector3[] { triangle.vertices[indexA].pos, triangle.vertices[indexB].pos });
            }
        }
    }
        /// <summary>
        /// Exports an element as an IFC assembly.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        /// <returns>True if exported successfully, false otherwise.</returns>
        public static bool ExportAssemblyInstanceElement(ExporterIFC exporterIFC, AssemblyInstance element,
                                                         ProductWrapper productWrapper)
        {
            if (element == null)
            {
                return(false);
            }

            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                IFCAnyHandle assemblyInstanceHnd = null;

                string          guid            = GUIDUtil.CreateGUID(element);
                IFCAnyHandle    ownerHistory    = ExporterCacheManager.OwnerHistoryHandle;
                IFCAnyHandle    localPlacement  = null;
                PlacementSetter placementSetter = null;
                IFCLevelInfo    levelInfo       = null;
                bool            relateToLevel   = true;

                string            ifcEnumType;
                IFCExportInfoPair exportAs = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType);
                if (exportAs.ExportInstance == IFCEntityType.IfcSystem)
                {
                    string name        = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                    string description = NamingUtil.GetDescriptionOverride(element, null);
                    string objectType  = NamingUtil.GetObjectTypeOverride(element, NamingUtil.GetFamilyAndTypeName(element));
                    assemblyInstanceHnd = IFCInstanceExporter.CreateSystem(file, guid, ownerHistory, name, description, objectType);

                    // Create classification reference when System has classification filed name assigned to it
                    ClassificationUtil.CreateClassification(exporterIFC, file, element, assemblyInstanceHnd);

                    HashSet <IFCAnyHandle> relatedBuildings = new HashSet <IFCAnyHandle>();
                    relatedBuildings.Add(ExporterCacheManager.BuildingHandle);

                    IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                                                                                                       ExporterCacheManager.OwnerHistoryHandle, null, null, assemblyInstanceHnd, relatedBuildings);

                    relateToLevel = false; // Already related to the building via IfcRelServicesBuildings.
                }
                else
                {
                    // Check for containment override
                    IFCAnyHandle overrideContainerHnd = null;
                    ElementId    overrideContainerId  = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainerHnd);

                    using (placementSetter = PlacementSetter.Create(exporterIFC, element, null, null, overrideContainerId, overrideContainerHnd))
                    {
                        IFCAnyHandle representation = null;

                        // We have limited support for exporting assemblies as other container types.
                        localPlacement = placementSetter.LocalPlacement;
                        levelInfo      = placementSetter.LevelInfo;

                        switch (exportAs.ExportInstance)
                        {
                        case IFCEntityType.IfcCurtainWall:
                            //case IFCExportType.IfcCurtainWallType:
                            //string cwPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType, "IfcCurtainWallType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateCurtainWall(exporterIFC, element, guid,
                                                                                        ownerHistory, localPlacement, representation, ifcEnumType);
                            break;

                        case IFCEntityType.IfcRamp:
                            string rampPredefinedType = RampExporter.GetIFCRampType(ifcEnumType);
                            //rampPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, rampPredefinedType, "IfcRampType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRamp(exporterIFC, element, guid,
                                                                                 ownerHistory, localPlacement, representation, rampPredefinedType);
                            break;

                        case IFCEntityType.IfcRoof:
                            //string roofPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType, "IfcRoofType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRoof(exporterIFC, element, guid,
                                                                                 ownerHistory, localPlacement, representation, ifcEnumType);
                            break;

                        case IFCEntityType.IfcStair:
                            string stairPredefinedType = StairsExporter.GetIFCStairType(ifcEnumType);
                            //stairPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, stairPredefinedType, "IfcStairType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateStair(exporterIFC, element, guid,
                                                                                  ownerHistory, localPlacement, representation, stairPredefinedType);
                            break;

                        case IFCEntityType.IfcWall:
                            //string wallPredefinedType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType, "IfcWallType");
                            assemblyInstanceHnd = IFCInstanceExporter.CreateWall(exporterIFC, element, guid,
                                                                                 ownerHistory, localPlacement, representation, ifcEnumType);
                            break;

                        default:
                            string objectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.GetFamilyAndTypeName(element));
                            IFCElementAssemblyType assemblyPredefinedType = GetPredefinedTypeFromObjectType(objectType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateElementAssembly(exporterIFC, element, guid,
                                                                                            ownerHistory, localPlacement, representation, IFCAssemblyPlace.NotDefined, assemblyPredefinedType);
                            break;
                        }
                    }
                }

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

                // relateToLevel depends on how the AssemblyInstance is being mapped to IFC, above.
                productWrapper.AddElement(element, assemblyInstanceHnd, levelInfo, null, relateToLevel, exportAs);

                ExporterCacheManager.AssemblyInstanceCache.RegisterAssemblyInstance(element.Id, assemblyInstanceHnd);

                tr.Commit();
                return(true);
            }
        }
Esempio n. 7
0
        // Fit the KMeans clusterer. Returns the score of this clustering.
        private double FitHelper(List <List <int> > X)
        {
            // duplicated code, but only twice, don't refactor yet
            var doublesList = new List <List <double> >();
            var rand        = new Random();

            _means = new List <List <double> >();

            foreach (var xi in X)
            {
                doublesList.Add(xi.Select(x => (double)x).ToList());
            }

            for (int i = 0; i < _k; i++)
            {
                var idx = rand.Next(0, X.Count - 1);
                _means.Add(doublesList[idx]);
            }

            // track whether means are still updating
            var stop = false;

            var labels = new Dictionary <int, List <List <double> > >();

            while (!stop)
            {
                for (int i = 0; i < _k; i++)
                {
                    labels[i] = new List <List <double> >();
                }

                // go through each point and assign it to the closest mean by euclidian distance
                var distances = ClassificationUtil.EuclidianDistance(doublesList, _means);

                for (int i = 0; i < distances.Count; i++)
                {
                    labels[distances[i].IndexOf(distances[i].Max())].Add(doublesList[i]);
                }

                // update location of means by weight of points assigned to it

                var prevMean = _means;

                for (int i = 0; i < _k; i++)
                {
                    _means[i] = ClassificationUtil.Average(labels[i]) ?? _means[i];
                }

                // keep track of old mean assignments throughout and if under
                // a certain number of points changed means, stop (or after some number of iterations)
                var firstNotSecond = prevMean.Except(_means).ToList();
                var secondNotFirst = _means.Except(prevMean).ToList();

                stop = !firstNotSecond.Any() && !secondNotFirst.Any();
            }

            double score = 0;

            // TODO rewrite -> it's unclear.
            // calculates a score using the distance of all points from their mean.
            foreach (var key in labels.Keys)
            {
                var doubleList = new List <List <double> >();
                doubleList.Add(_means[key]);

                var distanceList = ClassificationUtil.EuclidianDistance(labels[key], doubleList);
                score += distanceList.Count != 0 ? distanceList[0].Sum() : 0;
            }

            return(score);
        }
Esempio n. 8
0
    public static bool CutTriangleMesh(Mesh[] outputMeshes, Mesh sourceMesh, Plane cuttingPlane, Transform transform, Transform rotation, bool cap)
    {
        float epsilon = 0.00001f;

        debugPolyLoop       = new List <Vector3>();
        debugEdgePoints     = new List <Vector3>();
        debugEdges          = new List <Vector3[]>();
        debugLoopEdgePoints = new List <Vector3[]>();

        int vertCount = sourceMesh.vertexCount;

        Vector3[]           verts    = sourceMesh.vertices;
        Triangle3D.Vertex[] allVerts = new Triangle3D.Vertex[vertCount];
        for (int i = 0; i < vertCount; i++)
        {
            allVerts[i] = new Triangle3D.Vertex(transform.TransformPoint(verts[i]));
        }

        List <Triangle3D.Vertex> allVertList = new List <Triangle3D.Vertex>();

        Vector2[] originalUVs      = sourceMesh.uv;
        Vector3[] originalNormals  = sourceMesh.normals;
        Vector4[] originalTangents = sourceMesh.tangents;

        int triCount = sourceMesh.triangles.Length / 3;

        Triangle3D[] originalTriangles = new Triangle3D[triCount];

        int offset = 0;

        for (int j = 0; j < sourceMesh.subMeshCount; j++)
        {
            uint  triOffset       = 0;
            int[] subMeshIndices  = sourceMesh.GetTriangles(j);
            int   subMeshTriCount = subMeshIndices.Length / 3;

            for (int i = 0; i < subMeshTriCount; i++)
            {
                int idx0 = subMeshIndices[triOffset + 0];
                int idx1 = subMeshIndices[triOffset + 1];
                int idx2 = subMeshIndices[triOffset + 2];


                originalTriangles[offset++] = new Triangle3D(allVertList, new Triangle3D.Vertex[] { allVerts[idx0], allVerts[idx1], allVerts[idx2] }, new Vector3[] { originalNormals[idx0], originalNormals[idx1], originalNormals[idx2] }, new Vector2[] { originalUVs[idx0], originalUVs[idx1], originalUVs[idx2] }, new Vector4[] { originalTangents[idx0], originalTangents[idx1], originalTangents[idx2] }, new int[] { subMeshIndices[triOffset + 0], subMeshIndices[triOffset + 1], subMeshIndices[triOffset + 2] }, j);

                triOffset += 3;
            }
        }

        if (originalTriangles.Length > 0)
        {
            int          processedTriCount = 0;
            Triangle3D[] processedTris     = new Triangle3D[originalTriangles.Length * 3];

            ClassificationUtil.Classification prevSide = ClassificationUtil.Classification.UNDEFINED;
            foreach (Triangle3D originalTriangle in originalTriangles)
            {
                ClassificationUtil.Classification side;
                Triangle3D[] splitTriangles = TriangleUtil.SplitTriangleWithPlane(originalTriangle, cuttingPlane, epsilon, out side, cap);
                if (prevSide != ClassificationUtil.Classification.UNDEFINED && prevSide != side)
                {
                }
                prevSide = side;
                if (splitTriangles != null)
                {
                    // Triangle was cut
                    foreach (Triangle3D splitTriangle in splitTriangles)
                    {
                        processedTris[processedTriCount] = splitTriangle;
                        processedTriCount++;
                    }
                }

                else
                {
                    // Triangle was not cut
                    processedTris[processedTriCount] = originalTriangle;
                    processedTriCount++;
                }
            }

            int          triangleBucketACount = 0;
            int          triangleBucketBCount = 0;
            Triangle3D[] triangleBucketA      = new Triangle3D[processedTriCount];
            Triangle3D[] triangleBucketB      = new Triangle3D[processedTriCount];
            for (int i = 0; i < processedTriCount; i++)
            {
                ClassificationUtil.Classification[] classes;
                ClassificationUtil.Classification   triClass = ClassificationUtil.ClassifyPoints(processedTris[i].pos, cuttingPlane, out classes, epsilon);

                if (triClass == ClassificationUtil.Classification.FRONT)
                {
                    triangleBucketA[triangleBucketACount++] = processedTris[i];
                }

                else if (triClass == ClassificationUtil.Classification.BACK)
                {
                    triangleBucketB[triangleBucketBCount++] = processedTris[i];
                }
            }

            if (triangleBucketACount == 0 || triangleBucketBCount == 0)
            {
                return(false);
            }

            List <Triangle3D>        totalCapTriBucket  = new List <Triangle3D>();
            List <Triangle3D.Vertex> totalCapVertBucket = new List <Triangle3D.Vertex>();

            while (cap && debugEdges.Count > 2)
            {
                List <Triangle3D>        capTriBucket  = new List <Triangle3D>();
                List <Triangle3D.Vertex> capVertBucket = new List <Triangle3D.Vertex>();

                Triangle3D.Vertex[] sortedVerts = GetPolyLoop(ref debugEdges);

                if (sortedVerts != null)
                {
                    CapMesh(out capTriBucket, out capVertBucket, sortedVerts, transform, rotation, totalCapTriBucket.Count);
                }

                if (capVertBucket.Count > 2)
                {
                    for (int i = 0; i < capVertBucket.Count - 1; i++)
                    {
                        Debug.DrawLine(transform.TransformPoint(capVertBucket[i].pos), transform.TransformPoint(capVertBucket[i + 1].pos));
                    }
                    Debug.DrawLine(transform.TransformPoint(capVertBucket[capVertBucket.Count - 1].pos), transform.TransformPoint(capVertBucket[0].pos));
                }

                totalCapTriBucket.AddRange(capTriBucket);
                totalCapVertBucket.AddRange(capVertBucket);
            }

            if (triangleBucketACount > 0)
            {
                SortMesh(outputMeshes[0], triangleBucketA, triangleBucketACount, transform, totalCapTriBucket, totalCapVertBucket, false);
            }
            if (triangleBucketBCount > 0)
            {
                SortMesh(outputMeshes[1], triangleBucketB, triangleBucketBCount, transform, totalCapTriBucket, totalCapVertBucket, true);
            }
            return(true);
        }

        else
        {
            Debug.Log("source geometry empty");
            return(false);
        }
    }
Esempio n. 9
0
    public static bool CutTriangleMeshFast(Mesh[] outputMeshes, Mesh sourceMesh, Transform objectTransform, Transform planeTransform, bool cap)
    {
        float epsilon = 0.00001f;

        hashCheck           = new Dictionary <Vector3, int>();
        debugPolyLoop       = new List <Vector3>();
        debugEdgePoints     = new List <Vector3>();
        debugEdges          = new List <Vector3[]>();
        debugLoopEdgePoints = new List <Vector3[]>();

        int originalVertexCount = sourceMesh.vertexCount;

        Vector3[] originalVertices = sourceMesh.vertices;

        int originalIndexCount = sourceMesh.triangles.Length;

        int[] originalIndices = sourceMesh.triangles;

        Vector3 centre       = objectTransform.transform.InverseTransformPoint(planeTransform.position);
        Vector3 up           = objectTransform.transform.InverseTransformDirection(planeTransform.up);
        Plane   cuttingPlane = new Plane(up, centre);

        int totalIndexCount  = originalIndexCount;
        int totalVertexCount = originalVertexCount;

        int indexBufferCountA  = 0;
        int vertexBufferCountA = 0;

        Vector3[] vertexBufferA = new Vector3[totalVertexCount * 10];
        int[]     indexBufferA  = new int[originalIndexCount * 10];

        int indexBufferCountB  = 0;
        int vertexBufferCountB = 0;

        Vector3[] vertexBufferB = new Vector3[totalVertexCount * 10];
        int[]     indexBufferB  = new int[originalIndexCount * 10];

        Vector3[] points     = new Vector3[3];
        int[]     triIndices = new int[3];

        for (int i = 0; i < totalIndexCount; i += 3)
        {
            triIndices[0] = originalIndices[i];
            triIndices[1] = originalIndices[i + 1];
            triIndices[2] = originalIndices[i + 2];

            points[0] = originalVertices[triIndices[0]];
            points[1] = originalVertices[triIndices[1]];
            points[2] = originalVertices[triIndices[2]];

            int[]     newTris;
            Vector3[] newPoints;

            ClassificationUtil.Classification side;
            TriangleUtil.SplitTriangleWithPlane(
                ref totalVertexCount,
                points,
                triIndices,
                cuttingPlane,
                epsilon,
                out side,
                cap,
                out newTris,
                out newPoints);

            // Slice the triangle then classify which side it's on
            if (newTris != null)
            {
                for (int j = 0; j < newTris.Length; j += 3)
                {
                    ClassificationUtil.Classification[] classes;
                    ClassificationUtil.Classification   triClass = ClassificationUtil.ClassifyPoints(
                        new Vector3[] { newPoints[j + 0], newPoints[j + 1], newPoints[j + 2] },
                        cuttingPlane,
                        out classes,
                        epsilon);

                    //Debug.DrawLine(newPoints[j + 0], newPoints[j + 1]);
                    //Debug.DrawLine(newPoints[j + 1], newPoints[j + 2]);
                    //Debug.DrawLine(newPoints[j + 2], newPoints[j + 0]);

                    if (triClass == ClassificationUtil.Classification.FRONT)
                    {
                        indexBufferA[indexBufferCountA++]   = newTris[j + 0];
                        indexBufferA[indexBufferCountA++]   = newTris[j + 1];
                        indexBufferA[indexBufferCountA++]   = newTris[j + 2];
                        vertexBufferA[vertexBufferCountA++] = newPoints[j + 0];
                        vertexBufferA[vertexBufferCountA++] = newPoints[j + 1];
                        vertexBufferA[vertexBufferCountA++] = newPoints[j + 2];
                    }
                    else if (triClass == ClassificationUtil.Classification.BACK)
                    {
                        indexBufferB[indexBufferCountB++]   = newTris[j + 0];
                        indexBufferB[indexBufferCountB++]   = newTris[j + 1];
                        indexBufferB[indexBufferCountB++]   = newTris[j + 2];
                        vertexBufferB[vertexBufferCountB++] = newPoints[j + 0];
                        vertexBufferB[vertexBufferCountB++] = newPoints[j + 1];
                        vertexBufferB[vertexBufferCountB++] = newPoints[j + 2];
                    }
                }
            }
            else
            {
                ClassificationUtil.Classification[] classes;
                ClassificationUtil.Classification   triClass = ClassificationUtil.ClassifyPoints(
                    new Vector3[] { points[0], points[1], points[2] },
                    cuttingPlane,
                    out classes,
                    epsilon);

                //Debug.DrawLine(points[0], points[1], Color.red);
                //Debug.DrawLine(points[1], points[2], Color.red);
                //Debug.DrawLine(points[2], points[0], Color.red);

                if (triClass == ClassificationUtil.Classification.FRONT)
                {
                    indexBufferA[indexBufferCountA++]   = triIndices[0];
                    indexBufferA[indexBufferCountA++]   = triIndices[1];
                    indexBufferA[indexBufferCountA++]   = triIndices[2];
                    vertexBufferA[vertexBufferCountA++] = points[0];
                    vertexBufferA[vertexBufferCountA++] = points[1];
                    vertexBufferA[vertexBufferCountA++] = points[2];
                }
                else if (triClass == ClassificationUtil.Classification.BACK)
                {
                    indexBufferB[indexBufferCountB++]   = triIndices[0];
                    indexBufferB[indexBufferCountB++]   = triIndices[1];
                    indexBufferB[indexBufferCountB++]   = triIndices[2];
                    vertexBufferB[vertexBufferCountB++] = points[0];
                    vertexBufferB[vertexBufferCountB++] = points[1];
                    vertexBufferB[vertexBufferCountB++] = points[2];
                }
            }
        }

        if (indexBufferCountA > 0)
        {
            SortMesh(outputMeshes[0], indexBufferA, vertexBufferA, indexBufferCountA, false);
        }
        if (indexBufferCountB > 0)
        {
            SortMesh(outputMeshes[1], indexBufferB, vertexBufferB, indexBufferCountB, true);
        }
        return(true);
    }
    public static void SplitTriangleWithPlane(ref int vertexCount, Vector3[] points, int[] indices, Plane plane, float e, out ClassificationUtil.Classification side, bool cap, out int[] newTris, out Vector3[] newPoints)
    {
        ClassificationUtil.Classification[] classes;
        side = ClassificationUtil.ClassifyPoints(points, plane, out classes, e);

        if (side != ClassificationUtil.Classification.STRADDLE)
        {
            if (cap)
            {
                SetEdgeHash(0, 1, classes, points);
                SetEdgeHash(1, 2, classes, points);
                SetEdgeHash(2, 0, classes, points);
            }
            newTris = null;
            newPoints = null;
            return;
        }

        int totalVertexCount = vertexCount;

        //int iA;
        Vector3 pA;
        //Vector3 normA;
        //Vector2 uvA;
        //Vector4 tA;

        uint aLength = 0;
        int[] indicesA = new int[4];
        Vector3[] verticesA = new Vector3[4];
        //Vector3[] normalsA = new Vector3[4];
        //Vector2[] uvsA = new Vector2[4];
        //Vector4[] tangentsA = new Vector4[4];

        int iB;
        Vector3 pB;
        //Vector3 normB;
        //Vector2 uvB;
        //Vector4 tB;

        uint bLength = 0;
        int[] indicesB = new int[4];
        Vector3[] verticesB = new Vector3[4];
        //Vector3[] normalsB = new Vector3[4];
        //Vector2[] uvsB = new Vector2[4];
        //Vector4[] tangentsB = new Vector4[4];

        float sideA;
        float sideB;
        Intersection isect;
        //Vector2 newUV;

        List<Vector3> cVerts = new List<Vector3>();

        //int[] indices = triangles;
        //Triangle3D.Vertex[] points
        //Vector3[] normals = new Vector3[] { triangle.nv0, triangle.nv1, triangle.nv2 };
        //Vector2[] uvs = new Vector2[] { triangle.uv0, triangle.uv1, triangle.uv2 };
        //Vector4[] tangents = new Vector4[] { triangle.tv0, triangle.tv1, triangle.tv2 };

        float[] distance = new float[3];
        for (int i = 0; i < points.Length; i++)
        {
            distance[i] = plane.GetDistanceToPoint(points[i]);
        }

        for (int i = 0; i < points.Length; i++)
        {
            int j = (i + 1) % points.Length;

            //iA = indices[i];
            iB = indices[j];

            pA = points[i];
            pB = points[j];

            //uvA = uvs[i];
            //uvB = uvs[j];

            //normA = normals[i];
            //normB = normals[j];

            //tA = tangents[i];
            //tB = tangents[j];

            sideA = distance[i];
            sideB = distance[j];

            if (sideB > e)
            {
                if (sideA < -e)
                {
                    isect = Intersection.LinePlane(pA, pB, plane, e, null);
                    if (isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        SplitTriangleWithPlane(ref totalVertexCount, points, indices, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap, out newTris, out newPoints);
                    }

                    indicesA[aLength] = totalVertexCount;
                    indicesB[bLength] = totalVertexCount;
                    totalVertexCount++;

                    verticesA[aLength] = isect.vert;
                    verticesB[bLength] = isect.vert;

                    //newUV = InterpolateUV(uvA, uvB, isect.alpha);
                    //uvsA[aLength] = newUV;
                    //uvsB[bLength] = newUV;

                    //tangentsA[aLength] = tB;
                    //tangentsB[bLength] = tB;

                    //normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    //normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if (!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesA[aLength] = iB;
                verticesA[aLength] = pB;
                //uvsA[aLength] = uvB;
                //normalsA[aLength] = normB;
                //tangentsA[aLength] = tB;

                aLength++;
            }

            else if (sideB < -e)
            {
                if (sideA > e)
                {
                    isect = Intersection.LinePlane(pA, pB, plane, e, null);
                    if (isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        SplitTriangleWithPlane(ref totalVertexCount, points, indices, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap, out newTris, out newPoints);
                    }

                    indicesA[aLength] = totalVertexCount;
                    indicesB[bLength] = totalVertexCount;
                    totalVertexCount++;

                    verticesA[aLength] = isect.vert;
                    verticesB[bLength] = isect.vert;

                    //newUV = InterpolateUV(uvA, uvB, isect.alpha);
                    //uvsA[aLength] = newUV;
                    //uvsB[bLength] = newUV;

                    //tangentsA[aLength] = tB;
                    //tangentsB[bLength] = tB;

                    //normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    //normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if (!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesB[bLength] = iB;
                verticesB[bLength] = pB;
                //uvsB[bLength] = uvB;
                //normalsB[bLength] = normB;
                //tangentsB[bLength] = tB;

                bLength++;
            }
            else
            {
                indicesA[aLength] = iB;
                verticesA[aLength] = pB;
                //uvsA[aLength] = uvB;
                //normalsA[aLength] = normB;
                //tangentsA[aLength] = tB;

                aLength++;

                indicesB[bLength] = iB;
                verticesB[bLength] = pB;
                //uvsB[bLength] = uvB;
                //normalsB[bLength] = normB;
                //tangentsB[bLength] = tB;

                bLength++;

                cVerts.Add(pB);

                if (!cVerts.Contains(pB))
                {
                    cVerts.Add(pB);
                }
            }
        }

        for (int i = 0; i < cVerts.Count - 1; i++)
        {
            MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] });
        }

        if (aLength > 3 || bLength > 3)
        {
            newTris = new int[3 * 3];
            newPoints = new Vector3[3 * 3];
        }
        else
        {
            newTris = new int[3 * 2];
            newPoints = new Vector3[3 * 2];
        }

        newPoints[0] = verticesA[0];
        newPoints[1] = verticesA[1];
        newPoints[2] = verticesA[2];
        newTris[0] = indicesA[0];
        newTris[1] = indicesA[1];
        newTris[2] = indicesA[2];

        newPoints[3] = verticesB[0];
        newPoints[4] = verticesB[1];
        newPoints[5] = verticesB[2];
        newTris[3] = indicesB[0];
        newTris[4] = indicesB[1];
        newTris[5] = indicesB[2];

        if (aLength > 3)
        {
            newPoints[6] = verticesA[0];
            newPoints[7] = verticesA[2];
            newPoints[8] = verticesA[3];
            newTris[6] = indicesA[0];
            newTris[7] = indicesA[2];
            newTris[8] = indicesA[3];
        }
        else if (bLength > 3)
        {
            newPoints[6] = verticesB[0];
            newPoints[7] = verticesB[2];
            newPoints[8] = verticesB[3];
            newTris[6] = indicesB[0];
            newTris[7] = indicesB[2];
            newTris[8] = indicesB[3];
        }

        vertexCount = totalVertexCount;
    }
 public static Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side)
 {
     return SplitTriangleWithPlane(triangle, plane, e, out side, true);
 }
    public static Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side, bool cap)
    {
        ClassificationUtil.Classification[] classes;
        side = ClassificationUtil.ClassifyTriangle(triangle, plane, out classes, e);

        if(side != ClassificationUtil.Classification.STRADDLE)
        {
            if(cap)
            {
                SetEdge(0, 1, classes, triangle.pos);
                SetEdge(1, 2, classes, triangle.pos);
                SetEdge(2, 0, classes, triangle.pos);
            }
            return null;
        }

        //int iA;
        Triangle3D.Vertex pA;
        Vector3 normA;
        Vector2 uvA;
        //Vector4 tA;

        uint aLength = 0;
        int[] indicesA = new int[4];
        Triangle3D.Vertex[] verticesA = new Triangle3D.Vertex[4];
        Vector3[] normalsA = new Vector3[4];
        Vector2[] uvsA = new Vector2[4];
        Vector4[] tangentsA = new Vector4[4];

        int iB;
        Triangle3D.Vertex pB;
        Vector3 normB;
        Vector2 uvB;
        Vector4 tB;

        uint bLength = 0;
        int[] indicesB = new int[4];
        Triangle3D.Vertex[] verticesB = new Triangle3D.Vertex[4];
        Vector3[] normalsB = new Vector3[4];
        Vector2[] uvsB = new Vector2[4];
        Vector4[] tangentsB = new Vector4[4];

        float sideA;
        float sideB;
        Intersection isect;
        Vector2 newUV;

        List<Vector3> cVerts = new List<Vector3> ();

        int[] indices = new int[] { triangle.idxV0, triangle.idxV1, triangle.idxV2 };
        Triangle3D.Vertex[] points = new Triangle3D.Vertex[] { triangle.v0, triangle.v1, triangle.v2 };
        Vector3[] normals = new Vector3[] { triangle.nv0, triangle.nv1, triangle.nv2 };
        Vector2[] uvs = new Vector2[] { triangle.uv0, triangle.uv1, triangle.uv2 };
        Vector4[] tangents = new Vector4[] { triangle.tv0, triangle.tv1, triangle.tv2 };

        float[] distance = new float[3];
        for(int i = 0; i < points.Length; i++)
        {
            distance[i] = plane.GetDistanceToPoint(points[i].pos);
        }

        for(int i = 0; i < points.Length; i++)
        {
            int j = (i + 1) % points.Length;

            //iA = indices[i];
            iB = indices[j];

            pA = points[i];
            pB = points[j];

            uvA = uvs[i];
            uvB = uvs[j];

            normA = normals[i];
            normB = normals[j];

            //tA = tangents[i];
            tB = tangents[j];

            sideA = distance[i];
            sideB = distance[j];

            if(sideB > e)
            {
                if(sideA < -e)
                {
                    isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null);
                    if(isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        plane.distance += Mathf.Epsilon;
                        return SplitTriangleWithPlane(triangle, new Plane (plane.normal, plane.distance + 1.0f), e, out side, cap);
                    }

                    // New vertex was created
                    int newIndex = triangle.meshVertices.Count;
                    triangle.meshVertices.Add(new Triangle3D.Vertex (isect.vert));

                    indicesA[aLength] = newIndex;
                    indicesB[bLength] = newIndex;

                    verticesA[aLength] = new Triangle3D.Vertex (isect.vert);
                    verticesB[bLength] = new Triangle3D.Vertex (isect.vert);

                    newUV = InterpolateUV(uvA, uvB, isect.alpha);
                    uvsA[aLength] = newUV;
                    uvsB[bLength] = newUV;

                    tangentsA[aLength] = tB;
                    tangentsB[bLength] = tB;

                    normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if(!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesA[aLength] = iB;
                verticesA[aLength] = pB;
                uvsA[aLength] = uvB;
                normalsA[aLength] = normB;
                tangentsA[aLength] = tB;

                aLength++;
            }

            else if(sideB < -e)
            {
                if(sideA > e)
                {
                    isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null);
                    if(isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        return SplitTriangleWithPlane(triangle, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap);
                    }

                    // New vertex was created
                    int newIndex = triangle.meshVertices.Count;
                    triangle.meshVertices.Add(new Triangle3D.Vertex (isect.vert));

                    indicesA[aLength] = newIndex;
                    indicesB[bLength] = newIndex;

                    verticesA[aLength] = new Triangle3D.Vertex (isect.vert);
                    verticesB[bLength] = new Triangle3D.Vertex (isect.vert);

                    newUV = InterpolateUV(uvA, uvB, isect.alpha);
                    uvsA[aLength] = newUV;
                    uvsB[bLength] = newUV;

                    tangentsA[aLength] = tB;
                    tangentsB[bLength] = tB;

                    normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if(!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesB[bLength] = iB;
                verticesB[bLength] = pB;
                uvsB[bLength] = uvB;
                normalsB[bLength] = normB;
                tangentsB[bLength] = tB;

                bLength++;
            }
            else
            {
                indicesA[aLength] = iB;
                verticesA[aLength] = pB;
                uvsA[aLength] = uvB;
                normalsA[aLength] = normB;
                tangentsA[aLength] = tB;

                aLength++;

                indicesB[bLength] = iB;
                verticesB[bLength] = pB;
                uvsB[bLength] = uvB;
                normalsB[bLength] = normB;
                tangentsB[bLength] = tB;

                bLength++;

                cVerts.Add(pB.pos);

                if(!cVerts.Contains(pB.pos))
                {
                    cVerts.Add(pB.pos);
                }
            }
        }

        for(int i = 0; i < cVerts.Count - 1; i++)
        {
            MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] });
        }

        Triangle3D[] tris;
        if(aLength > 3 || bLength > 3)
        {
            tris = new Triangle3D[3];
        }

        else
        {
            tris = new Triangle3D[2];
        }

        tris[0] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[1], verticesA[2] }, new Vector3[] { normalsA[0], normalsA[1], normalsA[2] }, new Vector2[] { uvsA[0], uvsA[1], uvsA[2] }, new Vector4[] { tangentsA[0], tangentsA[1], tangentsA[2] }, new int[] { indicesA[0], indicesA[1], indicesA[2] }, triangle.subMeshGroup);

        tris[1] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[1], verticesB[2] }, new Vector3[] { normalsB[0], normalsB[1], normalsB[2] }, new Vector2[] { uvsB[0], uvsB[1], uvsB[2] }, new Vector4[] { tangentsB[0], tangentsB[1], tangentsB[2] }, new int[] { indicesB[0], indicesB[1], indicesB[2] }, triangle.subMeshGroup);

        if(aLength > 3)
        {
            tris[2] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[2], verticesA[3] }, new Vector3[] { normalsA[0], normalsA[2], normalsA[3] }, new Vector2[] { uvsA[0], uvsA[2], uvsA[3] }, new Vector4[] { tangentsA[0], tangentsA[2], tangentsA[3] }, new int[] { indicesA[0], indicesA[2], indicesA[3] }, triangle.subMeshGroup);

        }

        else if(bLength > 3)
        {
            tris[2] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[2], verticesB[3] }, new Vector3[] { normalsB[0], normalsB[2], normalsB[3] }, new Vector2[] { uvsB[0], uvsB[2], uvsB[3] }, new Vector4[] { tangentsB[0], tangentsB[2], tangentsB[3] }, new int[] { indicesB[0], indicesB[2], indicesB[3] }, triangle.subMeshGroup);
        }
        return tris;
    }
Esempio n. 13
0
    public static void SplitTriangleWithPlane(ref int vertexCount, Vector3[] points, int[] indices, Plane plane, float e, out ClassificationUtil.Classification side, bool cap, out int[] newTris, out Vector3[] newPoints)
    {
        ClassificationUtil.Classification[] classes;
        side = ClassificationUtil.ClassifyPoints(points, plane, out classes, e);

        if (side != ClassificationUtil.Classification.STRADDLE)
        {
            if (cap)
            {
                SetEdgeHash(0, 1, classes, points);
                SetEdgeHash(1, 2, classes, points);
                SetEdgeHash(2, 0, classes, points);
            }
            newTris   = null;
            newPoints = null;
            return;
        }

        int totalVertexCount = vertexCount;

        //int iA;
        Vector3 pA;
        //Vector3 normA;
        //Vector2 uvA;
        //Vector4 tA;

        uint aLength = 0;

        int[]     indicesA  = new int[4];
        Vector3[] verticesA = new Vector3[4];
        //Vector3[] normalsA = new Vector3[4];
        //Vector2[] uvsA = new Vector2[4];
        //Vector4[] tangentsA = new Vector4[4];

        int     iB;
        Vector3 pB;
        //Vector3 normB;
        //Vector2 uvB;
        //Vector4 tB;

        uint bLength = 0;

        int[]     indicesB  = new int[4];
        Vector3[] verticesB = new Vector3[4];
        //Vector3[] normalsB = new Vector3[4];
        //Vector2[] uvsB = new Vector2[4];
        //Vector4[] tangentsB = new Vector4[4];

        float        sideA;
        float        sideB;
        Intersection isect;
        //Vector2 newUV;

        List <Vector3> cVerts = new List <Vector3>();

        //int[] indices = triangles;
        //Triangle3D.Vertex[] points
        //Vector3[] normals = new Vector3[] { triangle.nv0, triangle.nv1, triangle.nv2 };
        //Vector2[] uvs = new Vector2[] { triangle.uv0, triangle.uv1, triangle.uv2 };
        //Vector4[] tangents = new Vector4[] { triangle.tv0, triangle.tv1, triangle.tv2 };

        float[] distance = new float[3];
        for (int i = 0; i < points.Length; i++)
        {
            distance[i] = plane.GetDistanceToPoint(points[i]);
        }

        for (int i = 0; i < points.Length; i++)
        {
            int j = (i + 1) % points.Length;

            //iA = indices[i];
            iB = indices[j];

            pA = points[i];
            pB = points[j];

            //uvA = uvs[i];
            //uvB = uvs[j];

            //normA = normals[i];
            //normB = normals[j];

            //tA = tangents[i];
            //tB = tangents[j];

            sideA = distance[i];
            sideB = distance[j];


            if (sideB > e)
            {
                if (sideA < -e)
                {
                    isect = Intersection.LinePlane(pA, pB, plane, e, null);
                    if (isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        SplitTriangleWithPlane(ref totalVertexCount, points, indices, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap, out newTris, out newPoints);
                    }

                    indicesA[aLength] = totalVertexCount;
                    indicesB[bLength] = totalVertexCount;
                    totalVertexCount++;

                    verticesA[aLength] = isect.vert;
                    verticesB[bLength] = isect.vert;

                    //newUV = InterpolateUV(uvA, uvB, isect.alpha);
                    //uvsA[aLength] = newUV;
                    //uvsB[bLength] = newUV;

                    //tangentsA[aLength] = tB;
                    //tangentsB[bLength] = tB;

                    //normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    //normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if (!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesA[aLength]  = iB;
                verticesA[aLength] = pB;
                //uvsA[aLength] = uvB;
                //normalsA[aLength] = normB;
                //tangentsA[aLength] = tB;

                aLength++;
            }

            else if (sideB < -e)
            {
                if (sideA > e)
                {
                    isect = Intersection.LinePlane(pA, pB, plane, e, null);
                    if (isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        SplitTriangleWithPlane(ref totalVertexCount, points, indices, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap, out newTris, out newPoints);
                    }

                    indicesA[aLength] = totalVertexCount;
                    indicesB[bLength] = totalVertexCount;
                    totalVertexCount++;

                    verticesA[aLength] = isect.vert;
                    verticesB[bLength] = isect.vert;

                    //newUV = InterpolateUV(uvA, uvB, isect.alpha);
                    //uvsA[aLength] = newUV;
                    //uvsB[bLength] = newUV;

                    //tangentsA[aLength] = tB;
                    //tangentsB[bLength] = tB;

                    //normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    //normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if (!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesB[bLength]  = iB;
                verticesB[bLength] = pB;
                //uvsB[bLength] = uvB;
                //normalsB[bLength] = normB;
                //tangentsB[bLength] = tB;

                bLength++;
            }
            else
            {
                indicesA[aLength]  = iB;
                verticesA[aLength] = pB;
                //uvsA[aLength] = uvB;
                //normalsA[aLength] = normB;
                //tangentsA[aLength] = tB;

                aLength++;

                indicesB[bLength]  = iB;
                verticesB[bLength] = pB;
                //uvsB[bLength] = uvB;
                //normalsB[bLength] = normB;
                //tangentsB[bLength] = tB;

                bLength++;

                cVerts.Add(pB);

                if (!cVerts.Contains(pB))
                {
                    cVerts.Add(pB);
                }
            }
        }

        for (int i = 0; i < cVerts.Count - 1; i++)
        {
            MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] });
        }

        if (aLength > 3 || bLength > 3)
        {
            newTris   = new int[3 * 3];
            newPoints = new Vector3[3 * 3];
        }
        else
        {
            newTris   = new int[3 * 2];
            newPoints = new Vector3[3 * 2];
        }

        newPoints[0] = verticesA[0];
        newPoints[1] = verticesA[1];
        newPoints[2] = verticesA[2];
        newTris[0]   = indicesA[0];
        newTris[1]   = indicesA[1];
        newTris[2]   = indicesA[2];

        newPoints[3] = verticesB[0];
        newPoints[4] = verticesB[1];
        newPoints[5] = verticesB[2];
        newTris[3]   = indicesB[0];
        newTris[4]   = indicesB[1];
        newTris[5]   = indicesB[2];

        if (aLength > 3)
        {
            newPoints[6] = verticesA[0];
            newPoints[7] = verticesA[2];
            newPoints[8] = verticesA[3];
            newTris[6]   = indicesA[0];
            newTris[7]   = indicesA[2];
            newTris[8]   = indicesA[3];
        }
        else if (bLength > 3)
        {
            newPoints[6] = verticesB[0];
            newPoints[7] = verticesB[2];
            newPoints[8] = verticesB[3];
            newTris[6]   = indicesB[0];
            newTris[7]   = indicesB[2];
            newTris[8]   = indicesB[3];
        }

        vertexCount = totalVertexCount;
    }
Esempio n. 14
0
    public static Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side, bool cap)
    {
        ClassificationUtil.Classification[] classes;
        side = ClassificationUtil.ClassifyTriangle(triangle, plane, out classes, e);


        if (side != ClassificationUtil.Classification.STRADDLE)
        {
            if (cap)
            {
                SetEdge(0, 1, classes, triangle.pos);
                SetEdge(1, 2, classes, triangle.pos);
                SetEdge(2, 0, classes, triangle.pos);
            }
            return(null);
        }

        //int iA;
        Triangle3D.Vertex pA;
        Vector3           normA;
        Vector2           uvA;
        //Vector4 tA;

        uint aLength = 0;

        int[] indicesA = new int[4];
        Triangle3D.Vertex[] verticesA = new Triangle3D.Vertex[4];
        Vector3[]           normalsA  = new Vector3[4];
        Vector2[]           uvsA      = new Vector2[4];
        Vector4[]           tangentsA = new Vector4[4];

        int iB;

        Triangle3D.Vertex pB;
        Vector3           normB;
        Vector2           uvB;
        Vector4           tB;

        uint bLength = 0;

        int[] indicesB = new int[4];
        Triangle3D.Vertex[] verticesB = new Triangle3D.Vertex[4];
        Vector3[]           normalsB  = new Vector3[4];
        Vector2[]           uvsB      = new Vector2[4];
        Vector4[]           tangentsB = new Vector4[4];

        float        sideA;
        float        sideB;
        Intersection isect;
        Vector2      newUV;

        List <Vector3> cVerts = new List <Vector3> ();

        int[] indices = new int[] { triangle.idxV0, triangle.idxV1, triangle.idxV2 };
        Triangle3D.Vertex[] points   = new Triangle3D.Vertex[] { triangle.v0, triangle.v1, triangle.v2 };
        Vector3[]           normals  = new Vector3[] { triangle.nv0, triangle.nv1, triangle.nv2 };
        Vector2[]           uvs      = new Vector2[] { triangle.uv0, triangle.uv1, triangle.uv2 };
        Vector4[]           tangents = new Vector4[] { triangle.tv0, triangle.tv1, triangle.tv2 };

        float[] distance = new float[3];
        for (int i = 0; i < points.Length; i++)
        {
            distance[i] = plane.GetDistanceToPoint(points[i].pos);
        }

        for (int i = 0; i < points.Length; i++)
        {
            int j = (i + 1) % points.Length;

            //iA = indices[i];
            iB = indices[j];

            pA = points[i];
            pB = points[j];

            uvA = uvs[i];
            uvB = uvs[j];

            normA = normals[i];
            normB = normals[j];

            //tA = tangents[i];
            tB = tangents[j];

            sideA = distance[i];
            sideB = distance[j];


            if (sideB > e)
            {
                if (sideA < -e)
                {
                    isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null);
                    if (isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        plane.distance += Mathf.Epsilon;
                        return(SplitTriangleWithPlane(triangle, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap));
                    }

                    // New vertex was created
                    int newIndex = triangle.meshVertices.Count;
                    triangle.meshVertices.Add(new Triangle3D.Vertex(isect.vert));

                    indicesA[aLength] = newIndex;
                    indicesB[bLength] = newIndex;

                    verticesA[aLength] = new Triangle3D.Vertex(isect.vert);
                    verticesB[bLength] = new Triangle3D.Vertex(isect.vert);


                    newUV         = InterpolateUV(uvA, uvB, isect.alpha);
                    uvsA[aLength] = newUV;
                    uvsB[bLength] = newUV;

                    tangentsA[aLength] = tB;
                    tangentsB[bLength] = tB;

                    normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if (!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesA[aLength]  = iB;
                verticesA[aLength] = pB;
                uvsA[aLength]      = uvB;
                normalsA[aLength]  = normB;
                tangentsA[aLength] = tB;

                aLength++;
            }

            else if (sideB < -e)
            {
                if (sideA > e)
                {
                    isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null);
                    if (isect.status != Intersection.IntersectionType.INTERSECTION)
                    {
                        return(SplitTriangleWithPlane(triangle, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap));
                    }

                    // New vertex was created
                    int newIndex = triangle.meshVertices.Count;
                    triangle.meshVertices.Add(new Triangle3D.Vertex(isect.vert));

                    indicesA[aLength] = newIndex;
                    indicesB[bLength] = newIndex;

                    verticesA[aLength] = new Triangle3D.Vertex(isect.vert);
                    verticesB[bLength] = new Triangle3D.Vertex(isect.vert);

                    newUV         = InterpolateUV(uvA, uvB, isect.alpha);
                    uvsA[aLength] = newUV;
                    uvsB[bLength] = newUV;

                    tangentsA[aLength] = tB;
                    tangentsB[bLength] = tB;

                    normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha);
                    normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha);

                    aLength++;
                    bLength++;

                    if (!cVerts.Contains(isect.vert))
                    {
                        cVerts.Add(isect.vert);
                    }
                }

                indicesB[bLength]  = iB;
                verticesB[bLength] = pB;
                uvsB[bLength]      = uvB;
                normalsB[bLength]  = normB;
                tangentsB[bLength] = tB;

                bLength++;
            }
            else
            {
                indicesA[aLength]  = iB;
                verticesA[aLength] = pB;
                uvsA[aLength]      = uvB;
                normalsA[aLength]  = normB;
                tangentsA[aLength] = tB;

                aLength++;

                indicesB[bLength]  = iB;
                verticesB[bLength] = pB;
                uvsB[bLength]      = uvB;
                normalsB[bLength]  = normB;
                tangentsB[bLength] = tB;

                bLength++;

                cVerts.Add(pB.pos);

                if (!cVerts.Contains(pB.pos))
                {
                    cVerts.Add(pB.pos);
                }
            }
        }

        for (int i = 0; i < cVerts.Count - 1; i++)
        {
            MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] });
        }

        Triangle3D[] tris;
        if (aLength > 3 || bLength > 3)
        {
            tris = new Triangle3D[3];
        }

        else
        {
            tris = new Triangle3D[2];
        }

        tris[0] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[1], verticesA[2] }, new Vector3[] { normalsA[0], normalsA[1], normalsA[2] }, new Vector2[] { uvsA[0], uvsA[1], uvsA[2] }, new Vector4[] { tangentsA[0], tangentsA[1], tangentsA[2] }, new int[] { indicesA[0], indicesA[1], indicesA[2] }, triangle.subMeshGroup);

        tris[1] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[1], verticesB[2] }, new Vector3[] { normalsB[0], normalsB[1], normalsB[2] }, new Vector2[] { uvsB[0], uvsB[1], uvsB[2] }, new Vector4[] { tangentsB[0], tangentsB[1], tangentsB[2] }, new int[] { indicesB[0], indicesB[1], indicesB[2] }, triangle.subMeshGroup);

        if (aLength > 3)
        {
            tris[2] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[2], verticesA[3] }, new Vector3[] { normalsA[0], normalsA[2], normalsA[3] }, new Vector2[] { uvsA[0], uvsA[2], uvsA[3] }, new Vector4[] { tangentsA[0], tangentsA[2], tangentsA[3] }, new int[] { indicesA[0], indicesA[2], indicesA[3] }, triangle.subMeshGroup);
        }

        else if (bLength > 3)
        {
            tris[2] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[2], verticesB[3] }, new Vector3[] { normalsB[0], normalsB[2], normalsB[3] }, new Vector2[] { uvsB[0], uvsB[2], uvsB[3] }, new Vector4[] { tangentsB[0], tangentsB[2], tangentsB[3] }, new int[] { indicesB[0], indicesB[2], indicesB[3] }, triangle.subMeshGroup);
        }
        return(tris);
    }
Esempio n. 15
0
        /// <summary>
        /// Exports an element as an IFC assembly.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        /// <returns>True if exported successfully, false otherwise.</returns>
        public static bool ExportAssemblyInstanceElement(ExporterIFC exporterIFC, AssemblyInstance element,
                                                         ProductWrapper productWrapper)
        {
            if (element == null)
            {
                return(false);
            }

            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                IFCAnyHandle assemblyInstanceHnd = null;

                string          guid            = GUIDUtil.CreateGUID(element);
                IFCAnyHandle    ownerHistory    = exporterIFC.GetOwnerHistoryHandle();
                string          name            = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element));
                string          description     = NamingUtil.GetDescriptionOverride(element, null);
                string          objectType      = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName());
                IFCAnyHandle    localPlacement  = null;
                PlacementSetter placementSetter = null;
                IFCLevelInfo    levelInfo       = null;

                string        ifcEnumType;
                IFCExportType exportAs = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType);
                if (exportAs == IFCExportType.IfcSystem)
                {
                    assemblyInstanceHnd = IFCInstanceExporter.CreateSystem(file, guid,
                                                                           ownerHistory, name, description, objectType);

                    // Create classification reference when System has classification filed name assigned to it
                    ClassificationUtil.CreateClassification(exporterIFC, file, element, assemblyInstanceHnd);

                    HashSet <IFCAnyHandle> relatedBuildings = new HashSet <IFCAnyHandle>();
                    relatedBuildings.Add(ExporterCacheManager.BuildingHandle);

                    IFCAnyHandle relServicesBuildings = IFCInstanceExporter.CreateRelServicesBuildings(file, GUIDUtil.CreateGUID(),
                                                                                                       exporterIFC.GetOwnerHistoryHandle(), null, null, assemblyInstanceHnd, relatedBuildings);
                }
                else
                {
                    using (placementSetter = PlacementSetter.Create(exporterIFC, element))
                    {
                        string       elementTag     = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element));
                        IFCAnyHandle representation = null;

                        // We have limited support for exporting assemblies as other container types.
                        localPlacement = placementSetter.LocalPlacement;
                        levelInfo      = placementSetter.LevelInfo;
                        ifcEnumType    = IFCValidateEntry.GetValidIFCType(element, ifcEnumType);

                        switch (exportAs)
                        {
                        case IFCExportType.IfcCurtainWall:
                            assemblyInstanceHnd = IFCInstanceExporter.CreateCurtainWall(file, guid,
                                                                                        ownerHistory, name, description, objectType, localPlacement, representation, elementTag);
                            break;

                        case IFCExportType.IfcRamp:
                            string rampPredefinedType = RampExporter.GetIFCRampType(ifcEnumType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRamp(file, guid,
                                                                                 ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                 rampPredefinedType);
                            break;

                        case IFCExportType.IfcRoof:
                            assemblyInstanceHnd = IFCInstanceExporter.CreateRoof(file, guid,
                                                                                 ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                 ifcEnumType);
                            break;

                        case IFCExportType.IfcStair:
                            string stairPredefinedType = StairsExporter.GetIFCStairType(ifcEnumType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateStair(file, guid,
                                                                                  ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                  stairPredefinedType);
                            break;

                        case IFCExportType.IfcWall:
                            assemblyInstanceHnd = IFCInstanceExporter.CreateWall(file, guid,
                                                                                 ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                 ifcEnumType);
                            break;

                        default:
                            IFCElementAssemblyType assemblyPredefinedType = GetPredefinedTypeFromObjectType(objectType);
                            assemblyInstanceHnd = IFCInstanceExporter.CreateElementAssembly(file, guid,
                                                                                            ownerHistory, name, description, objectType, localPlacement, representation, elementTag,
                                                                                            IFCAssemblyPlace.NotDefined, assemblyPredefinedType);
                            break;
                        }
                    }
                }

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

                bool relateToLevel = (levelInfo != null);
                productWrapper.AddElement(element, assemblyInstanceHnd, levelInfo, null, relateToLevel);

                ExporterCacheManager.AssemblyInstanceCache.RegisterAssemblyInstance(element.Id, assemblyInstanceHnd);

                tr.Commit();
                return(true);
            }
        }
        private static bool ExportGenericElementAsMappedItem(ExporterIFC exporterIFC,
                                                             Element element, GeometryElement geomElem, IFCExportInfoPair exportType,
                                                             ProductWrapper wrapper)
        {
            GeometryInstance geometryInstance = GetTheGeometryInstance(geomElem);

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

            GeometryElement exportGeometry = geometryInstance.GetSymbolGeometry();

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

            ElementId   symbolId    = geometryInstance.GetSymbolGeometryId()?.SymbolId ?? ElementId.InvalidElementId;
            ElementType elementType = element.Document.GetElement(symbolId) as ElementType;

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

            Transform originalTrf = geometryInstance.Transform;

            // Can't handle mirrored transforms yet.
            if (originalTrf.HasReflection)
            {
                return(false);
            }

            ElementId categoryId = CategoryUtil.GetSafeCategoryId(element);

            IFCFile file = exporterIFC.GetFile();

            IList <Transform>        repMapTrfList = new List <Transform>();
            BodyData                 bodyData      = null;
            FamilyTypeInfo           typeInfo      = new FamilyTypeInfo();
            IFCExtrusionCreationData extraParams   = typeInfo.extraParams;

            Transform offsetTransform = Transform.Identity;

            // We will create a new mapped type if we haven't already created the type.
            FamilyTypeInfo currentTypeInfo = ExporterCacheManager.FamilySymbolToTypeInfoCache.Find(symbolId, false, exportType);
            bool           found           = currentTypeInfo.IsValid();

            if (!found)
            {
                IList <IFCAnyHandle> representations3D = new List <IFCAnyHandle>();

                IFCAnyHandle dummyPlacement = ExporterUtil.CreateLocalPlacement(file, null, null);
                extraParams.SetLocalPlacement(dummyPlacement);

                using (TransformSetter trfSetter = TransformSetter.Create())
                {
                    BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow);

                    bodyData = BodyExporter.ExportBody(exporterIFC, element, categoryId,
                                                       ExporterUtil.GetSingleMaterial(element), exportGeometry,
                                                       bodyExporterOptions, extraParams);
                    typeInfo.MaterialIdList = bodyData.MaterialIds;
                    offsetTransform         = bodyData.OffsetTransform;

                    // This code does not handle openings yet.
                    // The intention for this is FabricationParts and DirectShapes which do not
                    // currently have opening.
                    // If they can have openings in the future, we can add this.
                    IFCAnyHandle bodyRepHnd = bodyData.RepresentationHnd;
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd) || extraParams.GetOpenings().Count > 0)
                    {
                        return(false);
                    }

                    representations3D.Add(bodyRepHnd);
                    repMapTrfList.Add(null);
                }

                typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC,
                                                                                extraParams.GetLocalPlacement());

                IFCAnyHandle typeStyle = FamilyInstanceExporter.CreateTypeEntityHandle(exporterIFC,
                                                                                       ref typeInfo, null, representations3D, repMapTrfList, null,
                                                                                       element, elementType, elementType, false, false,
                                                                                       exportType, out HashSet <IFCAnyHandle> propertySets);

                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle))
                {
                    wrapper.RegisterHandleWithElementType(elementType, exportType, typeStyle,
                                                          propertySets);

                    typeInfo.Style = typeStyle;

                    CategoryUtil.TryToCreateMaterialAssocation(exporterIFC, bodyData, elementType,
                                                               element, exportGeometry, typeStyle, typeInfo);

                    // Create other generic classification from ClassificationCode(s)
                    ClassificationUtil.CreateClassification(exporterIFC, file, elementType, typeStyle);
                    ClassificationUtil.CreateUniformatClassification(exporterIFC, file, elementType, typeStyle);
                }
            }

            if (found && !typeInfo.IsValid())
            {
                typeInfo = currentTypeInfo;
            }

            // we'll pretend we succeeded, but we'll do nothing.
            if (!typeInfo.IsValid())
            {
                return(false);
            }

            extraParams = typeInfo.extraParams;

            // We expect no openings, so always add to map.
            ExporterCacheManager.FamilySymbolToTypeInfoCache.Register(symbolId, false, exportType, typeInfo);

            XYZ       scaledMapOrigin = XYZ.Zero;
            Transform scaledTrf       = originalTrf.Multiply(typeInfo.StyleTransform);

            // create instance.
            IList <IFCAnyHandle> shapeReps = FamilyInstanceExporter.CreateShapeRepresentations(exporterIFC,
                                                                                               file, element, categoryId, typeInfo, scaledMapOrigin);

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

            Transform boundingBoxTrf = (offsetTransform != null) ? offsetTransform.Inverse : Transform.Identity;

            boundingBoxTrf = boundingBoxTrf.Multiply(scaledTrf.Inverse);
            IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, boundingBoxTrf);

            if (boundingBoxRep != null)
            {
                shapeReps.Add(boundingBoxRep);
            }

            IFCAnyHandle repHnd = (shapeReps.Count > 0) ? IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps) : null;

            using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, scaledTrf, null))
            {
                IFCAnyHandle instanceHandle            = null;
                IFCAnyHandle localPlacement            = setter.LocalPlacement;
                bool         materialAlreadyAssociated = false;

                // We won't create the instance if:
                // (1) we are exporting to CV2.0/RV, (2) we have no 2D, 3D, or bounding box geometry, and (3) we aren't exporting parts.
                if (!(repHnd == null &&
                      (ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2 ||
                       ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView)))
                {
                    string instanceGUID = GUIDUtil.CreateGUID(element);

                    bool isChildInContainer = element.AssemblyInstanceId != ElementId.InvalidElementId;

                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                    {
                        bool isBuildingElementProxy =
                            ((exportType.ExportInstance == IFCEntityType.IfcBuildingElementProxy) ||
                             (exportType.ExportType == IFCEntityType.IfcBuildingElementProxyType));

                        ElementId roomId = setter.UpdateRoomRelativeCoordinates(element,
                                                                                out IFCAnyHandle localPlacementToUse);
                        bool         containedInSpace = (roomId != ElementId.InvalidElementId) && (exportType.ExportInstance != IFCEntityType.IfcSystemFurnitureElement);
                        IFCAnyHandle ownerHistory     = ExporterCacheManager.OwnerHistoryHandle;

                        if (!isBuildingElementProxy)
                        {
                            instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, element, instanceGUID,
                                                                                        ownerHistory, localPlacementToUse, repHnd);
                        }
                        else
                        {
                            instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(exporterIFC, element, instanceGUID,
                                                                                            ownerHistory, localPlacementToUse, repHnd, exportType.ValidatedPredefinedType);
                        }

                        bool associateToLevel = !containedInSpace && !isChildInContainer;
                        wrapper.AddElement(element, instanceHandle, setter, extraParams, associateToLevel, exportType);
                        if (containedInSpace)
                        {
                            ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle);
                        }
                    }

                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle))
                    {
                        if (ElementFilteringUtil.IsMEPType(exportType) || ElementFilteringUtil.ProxyForMEPType(element, exportType))
                        {
                            ExporterCacheManager.MEPCache.Register(element, instanceHandle);
                        }

                        ExporterCacheManager.HandleToElementCache.Register(instanceHandle, element.Id);

                        if (!materialAlreadyAssociated)
                        {
                            // Create material association for the instance only if the the istance geometry is different from the type
                            // or the type does not have any material association
                            IFCAnyHandle constituentSetHnd = ExporterCacheManager.MaterialSetCache.FindConstituentSetHnd(symbolId);
                            if (IFCAnyHandleUtil.IsNullOrHasNoValue(constituentSetHnd) &&
                                bodyData != null && bodyData.RepresentationItemInfo != null && bodyData.RepresentationItemInfo.Count > 0)
                            {
                                CategoryUtil.CreateMaterialAssociationWithShapeAspect(exporterIFC, element, instanceHandle, bodyData.RepresentationItemInfo);
                            }
                            else
                            {
                                // Create material association in case if bodyData is null
                                CategoryUtil.CreateMaterialAssociation(exporterIFC, instanceHandle, typeInfo.MaterialIdList);
                            }
                        }

                        if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style))
                        {
                            ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle);
                        }
                    }
                }
            }
            return(true);
        }