/// <summary> /// Cap mesh /// </summary> /// <param name="color"></param> public void Cap(Color color) { if (Vertices == null || Vertices.Length < 6) { return; } // Convert to PolygonPointExt (2D + index) // Convention: bottom vertices start at 0, top at 1 - continue every 2 vertices var points = new List <PolygonPointExt>(); for (var idx = 0; idx < Vertices.Length; idx += 2) { points.Add(new PolygonPointExt(Vertices[idx].X, Vertices[idx].Z, idx)); } var poly = new Poly2TriPolygon.Polygon(points); try { P2T.Triangulate(poly); // Get resulting faces var faces = new List <int>(Faces); foreach (var tri in poly.Triangles) { var i0 = tri.Points[0] as PolygonPointExt; var i1 = tri.Points[1] as PolygonPointExt; var i2 = tri.Points[2] as PolygonPointExt; // apply to bottom faces.Add(i2.Idx); faces.Add(i1.Idx); faces.Add(i0.Idx); // apply to top faces.Add(i2.Idx + 1); faces.Add(i1.Idx + 1); faces.Add(i0.Idx + 1); // Add roof color Colors[i0.Idx + 1] = color; Colors[i2.Idx + 1] = color; Colors[i1.Idx + 1] = color; } Faces = faces.ToArray(); Normals = ComputeNormals(Vertices, Faces); } catch (Exception ex) { // TODO Console.WriteLine(ex.Message); } }
public PolygonObject( GameWorld world, Vertices points, Texture2D texture, float density = 1.0f, float friction = 0, float restitution = 0.7f, float destroy_threshold = 0.0f, String name = "PolygonObject", String texture_name = TNames.wall ) : base(world, texture, density, friction, restitution, is_destructible: ( destroy_threshold > 0 ), destroy_threshold: destroy_threshold, name: name, texture_name: texture_name) { List<PolygonPoint> polypoints = new List<PolygonPoint>(); foreach ( Vector2 pt in points ) { polypoints.Add( new PolygonPoint( pt.X, pt.Y ) ); } Polygon polygon = new Polygon( polypoints ); }
public static List<Vertices> ConvexPartition(DetectedVertices vertices) { Polygon poly = new Polygon(); foreach (var vertex in vertices) poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y)); if (vertices.Holes != null) { foreach (var holeVertices in vertices.Holes) { Polygon hole = new Polygon(); foreach (var vertex in holeVertices) hole.Points.Add(new TriangulationPoint(vertex.X, vertex.Y)); poly.AddHole(hole); } } DTSweepContext tcx = new DTSweepContext(); tcx.PrepareTriangulation(poly); DTSweep.Triangulate(tcx); List<Vertices> results = new List<Vertices>(); foreach (DelaunayTriangle triangle in poly.Triangles) { Vertices v = new Vertices(); foreach (TriangulationPoint p in triangle.Points) { v.Add(new FVector2((float)p.X, (float)p.Y)); } results.Add(v); } return results; }
/// <summary> /// Add a hole to the polygon. /// </summary> /// <param name="poly">A subtraction polygon fully contained inside this polygon.</param> public void AddHole(Polygon poly) { if (_holes == null) _holes = new List<Polygon>(); _holes.Add(poly); // XXX: tests could be made here to be sure it is fully inside // addSubtraction( poly.getPoints() ); }
public void Add(Polygon p) { _polygons.Add(p); }
public PolygonSet(Polygon poly) { _polygons.Add(poly); }
public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundfloats) { var length = Math.Max(1, Math.Abs((int)box.Length)); var height = box.Height; var flatten = (float)_flattenFactor.Value; var text = _text.GetValue(); var family = _fontChooser.GetFontFamily(); var style = Enum.GetValues(typeof(FontStyle)).OfType <FontStyle>().FirstOrDefault(fs => family.IsStyleAvailable(fs)); if (!family.IsStyleAvailable(style)) { family = FontFamily.GenericSansSerif; } var set = new List <Polygon>(); var sizes = new List <RectangleF>(); using (var bmp = new Bitmap(1, 1)) { using (var g = Graphics.FromImage(bmp)) { using (var font = new Font(family, length, style, GraphicsUnit.Pixel)) { for (var i = 0; i < text.Length; i += 32) { using (var sf = new StringFormat(StringFormat.GenericTypographic)) { var rem = Math.Min(text.Length, i + 32) - i; var range = Enumerable.Range(0, rem).Select(x => new CharacterRange(x, 1)).ToArray(); sf.SetMeasurableCharacterRanges(range); var reg = g.MeasureCharacterRanges(text.Substring(i, rem), font, new RectangleF(0, 0, float.MaxValue, float.MaxValue), sf); sizes.AddRange(reg.Select(x => x.GetBounds(g))); } } } } } var xOffset = box.Start.X; var yOffset = box.End.Y; for (var ci = 0; ci < text.Length; ci++) { var c = text[ci]; var size = sizes[ci]; var gp = new GraphicsPath(); gp.AddString(c.ToString(CultureInfo.InvariantCulture), family, (int)style, length, new PointF(0, 0), StringFormat.GenericTypographic); gp.Flatten(new System.Drawing.Drawing2D.Matrix(), flatten); var polygons = new List <Polygon>(); var poly = new List <PolygonPoint>(); for (var i = 0; i < gp.PointCount; i++) { var type = gp.PathTypes[i]; var point = gp.PathPoints[i]; poly.Add(new PolygonPoint(point.X + xOffset, -point.Y + yOffset)); if ((type & 0x80) == 0x80) { polygons.Add(new Polygon(poly)); poly.Clear(); } } var tri = new List <Polygon>(); Polygon polygon = null; foreach (var p in polygons) { if (polygon == null) { polygon = p; tri.Add(p); } else if (p.CalculateWindingOrder() != polygon.CalculateWindingOrder()) { polygon.AddHole(p); } else { polygon = null; tri.Add(p); } } foreach (var pp in tri) { try { P2T.Triangulate(pp); set.Add(pp); } catch { // Ignore } } xOffset += size.Width; } var zOffset = box.Start.Z; foreach (var polygon in set) { foreach (var t in polygon.Triangles) { var points = t.Points.Select(x => new Vector3((float)x.X, (float)x.Y, zOffset).Round(roundfloats)).ToList(); var faces = new List <Vector3[]>(); // Add the vertical faces var z = new Vector3(0, 0, height).Round(roundfloats); for (var j = 0; j < points.Count; j++) { var next = (j + 1) % points.Count; faces.Add(new[] { points[j], points[j] + z, points[next] + z, points[next] }); } // Add the top and bottom faces faces.Add(points.ToArray()); faces.Add(points.Select(x => x + z).Reverse().ToArray()); // Nothing new here, move along var solid = new Solid(generator.Next("MapObject")); solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour())); foreach (var arr in faces) { var face = new Face(generator.Next("Face")) { Plane = new Plane(arr[0], arr[1], arr[2]), Texture = { Name = texture } }; face.Vertices.AddRange(arr.Select(x => x.Round(roundfloats))); solid.Data.Add(face); } solid.DescendantsChanged(); yield return(solid); } } }
public static MeshGeometryModel3D Create3DPolygon(List <Vector2> points, float height, Material material) { MeshBuilder builder = new MeshBuilder(); if (points.Count < 3) { return(null); } // Create poly now to indicate winding order Polygon_Poly2Tri upPolygon = new Polygon_Poly2Tri( points: points.Select(point => new PolygonPoint(point.X, point.Y))); List <Vector2> pointByClockwise = upPolygon.WindingOrder == Point2DList.WindingOrderType.AntiClockwise ? points.AsEnumerable().Reverse().ToList() : points; // Adding walls Vector3 firstUpPoint = pointByClockwise.First().AddZ(height); Vector3 firstDownPoint = pointByClockwise.First().AddZ(0); Vector3 lastUpPoint = firstUpPoint; Vector3 lastDownPoint = firstDownPoint; for (int i = 1; i < pointByClockwise.Count; i++) { Vector3 currentUpPoint = pointByClockwise[i].AddZ(height); Vector3 currentDownPoint = pointByClockwise[i].AddZ(0); builder.AddQuad( currentDownPoint.Map(), lastDownPoint.Map(), lastUpPoint.Map(), currentUpPoint.Map()); lastUpPoint = currentUpPoint; lastDownPoint = currentDownPoint; } // Create cycle builder.AddQuad( firstDownPoint.Map(), lastDownPoint.Map(), lastUpPoint.Map(), firstUpPoint.Map()); // Adding Upper Part P2T.Triangulate(upPolygon); foreach (var trianglePoints in upPolygon.Triangles.Select(x => x.Points)) { builder.AddTriangle( p0: new Vector3_SharpDX((float)trianglePoints.Item0.X, (float)trianglePoints.Item0.Y, height), p1: new Vector3_SharpDX((float)trianglePoints.Item1.X, (float)trianglePoints.Item1.Y, height), p2: new Vector3_SharpDX((float)trianglePoints.Item2.X, (float)trianglePoints.Item2.Y, height)); } MeshGeometry3D polyWall = builder.ToMesh(); MeshGeometryModel3D element = new MeshGeometryModel3D() { Geometry = polyWall, Material = material }; return(element); }
/// <summary> /// Create builidng esh /// </summary> /// <param name="building"></param> /// <returns></returns> public static Mesh CreateMesh(BuildingPart building) { var minY = building.Body.min_height; var maxY = building.Body.height; var poly = building.Footprint; var total = poly.Points.Count; if (poly is MultiPolygon) { (poly as MultiPolygon).Holes.ForEach(x => total += x.Points.Count); } // Build mesh var vertices = new Vector3[total * 2]; var faces = new List <int>(); var colors = Enumerable.Repeat(building.Body.surface.color, total * 2).ToArray(); // Create vertices and polygon for triangulation var idx = 0; var P2Tpoints = new List <PolygonPointExt>(); foreach (var point in poly.Points) { vertices[idx] = new Vector3(point.X, minY, -point.Y); vertices[idx + total] = new Vector3(point.X, maxY, -point.Y); P2Tpoints.Add(new PolygonPointExt(point.X, point.Y, idx++)); } var P2Tpoly = new Poly2TriPolygon.Polygon(P2Tpoints); // add faces = 2 triangles for (var i = 0; i < poly.Points.Count - 1; i++) { faces.Add(i + total); faces.Add(i); faces.Add(i + 1); faces.Add(i + total); faces.Add(i + 1); faces.Add(i + total + 1); } if (poly is MultiPolygon) { (poly as MultiPolygon).Holes.ForEach(hole => { // Create holes vertices and holes for triangulation var P2Thole = new List <PolygonPointExt>(); for (var i = 0; i < hole.Points.Count; i++) { vertices[idx + i] = new Vector3(hole.Points[i].X, minY, -hole.Points[i].Y); vertices[idx + i + total] = new Vector3(hole.Points[i].X, maxY, -hole.Points[i].Y); P2Thole.Add(new PolygonPointExt(hole.Points[i].X, hole.Points[i].Y, idx + i)); } // Create holes faces = 2 triangles for (var i = 0; i < hole.Points.Count - 1; i++) { faces.Add(idx + i + total); faces.Add(idx + i); faces.Add(idx + i + 1); faces.Add(idx + i + total); faces.Add(idx + i + 1); faces.Add(idx + i + total + 1); } P2Tpoly.AddHole(new Poly2TriPolygon.Polygon(P2Thole)); idx += hole.Points.Count; }); } try { P2T.Triangulate(P2Tpoly); // Add triangulated top faces foreach (var tri in P2Tpoly.Triangles) { var i0 = tri.Points[0] as PolygonPointExt; var i1 = tri.Points[1] as PolygonPointExt; var i2 = tri.Points[2] as PolygonPointExt; // apply to bottom // faces.Add(i2.Idx); // faces.Add(i1.Idx); // faces.Add(i0.Idx); // apply to top faces.Add(i2.Idx + total); faces.Add(i1.Idx + total); faces.Add(i0.Idx + total); // Add roof color colors[i0.Idx + total] = building.Roof.surface.color; colors[i2.Idx + total] = building.Roof.surface.color; colors[i1.Idx + total] = building.Roof.surface.color; } return(new Mesh(vertices, faces.ToArray(), colors)); } catch (Exception ex) { Console.WriteLine(ex.Message); } return(null); }
public static List<Vertices> ConvexPartition(Vertices vertices) { Polygon poly = new Polygon(); foreach (FVector2 vertex in vertices) { poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y)); } DTSweepContext tcx = new DTSweepContext(); tcx.PrepareTriangulation(poly); DTSweep.Triangulate(tcx); List<Vertices> results = new List<Vertices>(); foreach (DelaunayTriangle triangle in poly.Triangles) { Vertices v = new Vertices(); foreach (TriangulationPoint p in triangle.Points) { v.Add(new FVector2((float)p.X, (float)p.Y)); } results.Add(v); } return results; }