/// <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"))); } }
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); } }
// 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); }
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); } }
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; }
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, 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); }
/// <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); }