private void TriangulateButton_OnClick(object sender, RoutedEventArgs e) { List <int> triangleIndices; // We will manually create the triangle indices with Triangulator // This way we can catch the FormatException in case the _points are not correct (for example if lines intersect each other) // If we do not need to show the exception message we could simply call the CreateExtrudedMeshGeometry without triangleIndices as second parameter. // Than in case the _points were not correct we would simply get null back. // Triangulator takes a list of 2D points and connects them with creating triangles (it creates triangle indices that are declared as Int32Collection). // If we would only need triangle indices, we could also use static Triangulate method, but we need IsClockwise property later //triangleIndices = Ab3d.Utilities.Triangulator.Triangulate(_points); // Adjust shape positions so that (0,0) is at the center of the area // We also invert y so that y increased upwards (as the blue arrows shows) and not downwards as in Canvas coordinate system var centeredShapePositions = InvertYAndCenterPoints(_shapePositions); Ab3d.Utilities.Triangulator triangulator = new Ab3d.Utilities.Triangulator(centeredShapePositions); try { triangleIndices = triangulator.CreateTriangleIndices(); } catch (FormatException ex) { // Usually thrown when the polygon lines intersect each other MessageBox.Show(ex.Message); return; } Vector3D extrudeVector, shapeYVector3D; bool isSuccess = GetExtrudeAndUpVectors(out extrudeVector, out shapeYVector3D); if (!isSuccess) { return; } // Get the 3D vector for the positions x axis direction (upVector3D is direction of y axis) Vector3D shapeXVector3D = Vector3D.CrossProduct(extrudeVector, shapeYVector3D); if (shapeXVector3D.LengthSquared < 0.001) { MessageBox.Show("Cannot extrude shape because extrudeVector and shapeYVector are parallel and not perpendicular."); return; } // Convert list of 2D positions into a list of 3D positions with specifying custom X axis and Y axis Point3DCollection positions = Convert2DTo3DPositions(centeredShapePositions, shapeXVector3D, shapeYVector3D); //for (int i = 0; i < _shapePositions.Count; i++) // positions.Add(new Point3D(_shapePositions[i].X + xOffset, yOffset, _shapePositions[i].Y + zOffset)); var mesh = new MeshGeometry3D(); mesh.Positions = positions; mesh.TriangleIndices = new Int32Collection(triangleIndices); CreateGeometryModel(mesh); _isExtrudedModelShown = false; }
public ExtrudeAlongPathSample() { InitializeComponent(); // First prepare two 2D shapes: var letterTShapePositions = new Point[] { new Point(5, 0), new Point(-5, 0), new Point(-5, 40), new Point(-20, 40), new Point(-20, 50), new Point(20, 50), new Point(20, 40), new Point(5, 40), }; var ellipsePositionList = new List <Point>(); for (int i = 0; i < 360; i += 20) { ellipsePositionList.Add(new Point(Math.Sin(i / 180.0 * Math.PI) * 20, Math.Cos(i / 180.0 * Math.PI) * 10)); } // Now define a simple 3D path: var extrudePath = new Point3D[] { new Point3D(0, 0, 0), new Point3D(0, 90, 0), new Point3D(-20, 110, 0), new Point3D(-50, 130, 20), new Point3D(-50, 130, 100), }; // Create extruded models: MeshGeometry3D extrudedMesh1 = Mesh3DFactory.CreateExtrudedMeshGeometry( shapePositions: ellipsePositionList, extrudePathPositions: extrudePath, shapeYVector3D: new Vector3D(0, 0, -1), isClosed: true, isSmooth: true); CreateGeometryModel(extrudedMesh1, offset: new Vector3D(-150, 0, -50), setBackMaterial: false); var extrudedMesh2 = Mesh3DFactory.CreateExtrudedMeshGeometry( shapePositions: ellipsePositionList, extrudePathPositions: extrudePath, shapeYVector3D: new Vector3D(0, 0, -1), isClosed: false, isSmooth: false); // Because this mesh will not be closed, we will be able to see inside - so set the back material to dim gray. CreateGeometryModel(extrudedMesh2, offset: new Vector3D(0, 0, -50), setBackMaterial: true); // Until now we only provided the shape positions to the CreateExtrudedMeshGeometry. // This method then triangulated the shape in case it was closed. // Here we manually triangulate the shape and provide the shapeTriangleIndices to CreateExtrudedMeshGeometry: var triangulator = new Ab3d.Utilities.Triangulator(letterTShapePositions); // NOTE: CreateTriangleIndices can throw FormatException when the positions are not correctly defined (for example if the lines intersect each other). List <int> triangleIndices = triangulator.CreateTriangleIndices(); MeshGeometry3D extrudedMesh = Mesh3DFactory.CreateExtrudedMeshGeometry( shapePositions: letterTShapePositions, shapeTriangleIndices: triangleIndices, extrudePathPositions: extrudePath, shapeYVector3D: new Vector3D(0, 0, -1), isClosed: true, isSmooth: false, flipNormals: triangulator.IsClockwise); // If true than normals are flipped - used when positions are defined in a counter clockwise order CreateGeometryModel(extrudedMesh, offset: new Vector3D(150, 0, -50), setBackMaterial: false); }