public static TriangleInfoList ConvertStringToTrianglesWithOuterPath(string text, FontStyle fontStyle, Polygon outerPath, out PolygonSet textAsPolygonSet, float glyphFontSize = 50f) { FontFamily fontFamily = FontFamily.GenericSansSerif; textAsPolygonSet = new PolygonSet(); var triangles = new TriangleInfoList(); try { var textAsPolygons = GeneratePolygonsFromGlyph(fontFamily, fontStyle, text, glyphFontSize, true); textAsPolygonSet = CreateSetFromList(textAsPolygons); var polygonSetWithOuterPath = new PolygonSet(); foreach (var t in textAsPolygonSet.Polygons) { foreach (var hole in t.Holes) { polygonSetWithOuterPath.Add(hole); } //t.Holes.Clear(); outerPath.Holes.Add(t); } polygonSetWithOuterPath.Add(outerPath); P2T.Triangulate(polygonSetWithOuterPath); foreach (var polygon in polygonSetWithOuterPath.Polygons) { foreach (var polyTriangle in polygon.Triangles) { var triangle = new Triangle(); var triangleIndex = 0; foreach (var trianglePoint in polyTriangle.Points) { triangle.Vectors[triangleIndex].Position.X = (float)trianglePoint.X; triangle.Vectors[triangleIndex].Position.Y = (float)trianglePoint.Y; triangleIndex++; } triangles[0].Add(triangle); } } } catch (Exception exc) { Debug.WriteLine(exc); } return(triangles); }
static void ProcessSetLevel(PolygonSet set, PolygonHierachy current) { while (current != null) { var poly = current.Current; foreach (var child in current.Childs) { poly.AddHole(child.Current); foreach (var grandchild in child.Childs) { ProcessSetLevel(set, grandchild); } } set.Add(poly); current = current.Next; } }
static void InsertIntoSet(PolygonSet set, Polygon poly) { //first test to see if any of the existing polygons are inside our input. for (int i = set.Polygons.Count - 1; i >= 0; i--) { if (TryInsertHole(poly, set.Polygons[i])) { set.Polygons.RemoveAt(i); //we go from the end, so the indices remain valid. } } foreach (var item in set.Polygons) { if (TryInsertHole(item, poly)) { return; //nothing more to do. } } set.Add(poly); }
public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var width = box.Width; 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 PolygonSet(); var sizes = new List <RectangleF>(); using (var bmp = new Bitmap(1, 1)) { using (var g = System.Drawing.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.DX; var yOffset = box.End.DY; 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.Polygons) { foreach (var t in polygon.Triangles) { var points = t.Points.Select(x => new Coordinate((decimal)x.X, (decimal)x.Y, zOffset).Round(roundDecimals)).ToList(); var faces = new List <Coordinate[]>(); // Add the vertical faces var z = new Coordinate(0, 0, height).Round(roundDecimals); 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.GetNextObjectID()) { Colour = Colour.GetRandomBrushColour() }; foreach (var arr in faces) { var face = new Face(generator.GetNextFaceID()) { Parent = solid, Plane = new Plane(arr[0], arr[1], arr[2]), Colour = solid.Colour, Texture = { Texture = texture } }; face.Vertices.AddRange(arr.Select(x => new Vertex(x, face))); face.UpdateBoundingBox(); face.AlignTextureToFace(); solid.Faces.Add(face); } solid.UpdateBoundingBox(); yield return(solid); } } }
private void RefreshAsset(string name) { var asset = _data.GetAsset(name); _sw.Reset(); foreach (var poly in asset.Polygons) { var v = new ContourVertex[poly.Count]; for (int i = 0; i < poly.Count; i++) { v[i].Position = new Vec3 { X = poly[i].X, Y = poly[i].Y }; v[i].Data = poly[i].Color; } _sw.Start(); _tess.AddContour(v, poly.Orientation); _sw.Stop(); } _sw.Start(); _tess.Tessellate(_windingRule, ElementType.Polygons, _polySize, VertexCombine); _sw.Stop(); var output = new PolygonSet(); for (int i = 0; i < _tess.ElementCount; i++) { var poly = new Polygon(); for (int j = 0; j < _polySize; j++) { int index = _tess.Elements[i * _polySize + j]; if (index == -1) continue; var v = new PolygonPoint { X = _tess.Vertices[index].Position.X, Y = _tess.Vertices[index].Position.Y, Color = (Color)_tess.Vertices[index].Data }; poly.Add(v); } output.Add(poly); } statusMain.Text = string.Format("{0:F3} ms - {1} polygons (of {2} vertices) {3}", _sw.Elapsed.TotalMilliseconds, _tess.ElementCount, _polySize, _polySize == 3 ? "... triangles" : ""); _canvas.Input = asset.Polygons; _canvas.Output = output; _canvas.Invalidate(); }
public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var width = box.Width; 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 PolygonSet(); var sizes = new List<RectangleF>(); using (var bmp = new Bitmap(1,1)) { using (var g = System.Drawing.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.DX; var yOffset = box.End.DY; 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.Polygons) { foreach (var t in polygon.Triangles) { var points = t.Points.Select(x => new Coordinate((decimal) x.X, (decimal) x.Y, zOffset).Round(roundDecimals)).ToList(); var faces = new List<Coordinate[]>(); // Add the vertical faces var z = new Coordinate(0, 0, height).Round(roundDecimals); 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.GetNextObjectID()) {Colour = Colour.GetRandomBrushColour()}; foreach (var arr in faces) { var face = new Face(generator.GetNextFaceID()) { Parent = solid, Plane = new Plane(arr[0], arr[1], arr[2]), Colour = solid.Colour, Texture = {Texture = texture} }; face.Vertices.AddRange(arr.Select(x => new Vertex(x, face))); face.UpdateBoundingBox(); face.AlignTextureToFace(); solid.Faces.Add(face); } solid.UpdateBoundingBox(); yield return solid; } } }
private static PolygonSet FromTess(Tess tess) { var output = new PolygonSet(); for (int i = 0; i < tess.ElementCount; i++) { var poly = new Polygon(); for (int j = 0; j < 3; j++) { int index = tess.Elements[i * 3 + j]; if (index == -1) continue; var v = new PolygonPoint { X = tess.Vertices[index].Position.X, Y = tess.Vertices[index].Position.Y }; poly.Add(v); } output.Add(poly); } return output; }
private static PolygonSet FromP2T(Poly2Tri.PolygonSet pset) { var result = new PolygonSet(); foreach (var poly in pset.Polygons) { foreach (var tri in poly.Triangles) { var rtri = new Polygon(); rtri.Add(new PolygonPoint { X = tri.Points[0].Xf, Y = tri.Points[0].Yf }); rtri.Add(new PolygonPoint { X = tri.Points[1].Xf, Y = tri.Points[1].Yf }); rtri.Add(new PolygonPoint { X = tri.Points[2].Xf, Y = tri.Points[2].Yf }); result.Add(rtri); } } return result; }
private static PolygonSet FromTess(Tess tess) { var output = new PolygonSet(); for (int i = 0; i < tess.Elements.Count / 3; i++) { var poly = new Polygon(); for (int j = 0; j < 3; j++) { int index = tess.Elements[i * 3 + j]; if (index == -1) continue; var v = new PolygonPoint { X = tess.Vertices[index].X, Y = tess.Vertices[index].Y, //Color = _tess.Vertices[index].Data != null ? (Color)_tess.Vertices[index].Data : Color.White }; poly.Add(v); } output.Add(poly); } return output; }
public static ComplexShape ToTriangles(this ComplexShape p_polygon) { var v_trianglesShape = new ComplexShape(); List <PolygonShape> v_holes = p_polygon.GetHoles(); List <PolygonShape> v_nonHoles = p_polygon.GetNonHoles(); Dictionary <PolygonShape, List <PolygonShape> > v_shapeAndHoles = new Dictionary <PolygonShape, List <PolygonShape> >(); foreach (var v_shape in v_nonHoles) { if (!v_shapeAndHoles.ContainsKey(v_shape)) { v_shapeAndHoles.Add(v_shape, new List <PolygonShape>()); } } //Build dictionary that contains Hole Hierarchy per Shape foreach (var v_hole in v_holes) { foreach (var v_shape in v_nonHoles) { bool v_isInsideShape = true; //Detect if Point is in Shape foreach (var v_holeVertice in v_hole.Vertices) { if (!v_shape.PointInShape(v_holeVertice)) { v_isInsideShape = false; break; } } if (v_isInsideShape) { if (!v_shapeAndHoles[v_shape].Contains(v_hole)) { v_shapeAndHoles[v_shape].Add(v_hole); } break; } } } if (v_shapeAndHoles.Count > 0) { PolygonSet v_polygonSet = new PolygonSet(); foreach (var v_shape in v_shapeAndHoles.Keys) { var v_P2TPolygon = v_shape.ToP2TPolygon(v_shapeAndHoles[v_shape]); if (v_P2TPolygon != null) { v_polygonSet.Add(v_P2TPolygon); } } P2T.Triangulate(v_polygonSet); foreach (var v_P2TPolygon in v_polygonSet.Polygons) { foreach (var v_P2TTriangle in v_P2TPolygon.Triangles) { PolygonShape v_triangle = new PolygonShape(); foreach (var v_point in v_P2TTriangle.Points) { v_triangle.Vertices.Add(new Vector2((float)v_point.X, (float)v_point.Y)); } if (v_triangle.GetPolygonArea() != 0) { v_triangle.RecalcBounds(); if (!v_triangle.IsOrientedClockwise()) { v_triangle.ReverseOrientation(); } v_trianglesShape.AddShape(v_triangle, false); } } } } return(v_trianglesShape); }