public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture) { var solid = new Solid(generator.GetNextObjectID()) { Colour = Colour.GetRandomBrushColour() }; // The lower Z plane will be base, the x planes will be triangles var c1 = new Coordinate(box.Start.X, box.Start.Y, box.Start.Z); var c2 = new Coordinate(box.End.X, box.Start.Y, box.Start.Z); var c3 = new Coordinate(box.End.X, box.End.Y, box.Start.Z); var c4 = new Coordinate(box.Start.X, box.End.Y, box.Start.Z); var c5 = new Coordinate(box.Center.X, box.Start.Y, box.End.Z); var c6 = new Coordinate(box.Center.X, box.End.Y, box.End.Z); var faces = new[] { new[] { c1, c2, c3, c4 }, new[] { c2, c1, c5 }, new[] { c5, c6, c3, c2 }, new[] { c4, c3, c6 }, new[] { c6, c5, c1, c4 } }; 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; }
public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var solid = new Solid(generator.GetNextObjectID()) { Colour = Colour.GetRandomBrushColour() }; // The higher Z plane will be triangle, with the lower X value getting the two corners var c1 = new Coordinate(box.Start.X, box.Start.Y, box.End.Z).Round(roundDecimals); var c2 = new Coordinate(box.End.X, box.Start.Y, box.End.Z).Round(roundDecimals); var c3 = new Coordinate(box.Center.X, box.End.Y, box.End.Z).Round(roundDecimals); var c4 = new Coordinate(box.Center.X, box.Center.Y, box.Start.Z).Round(roundDecimals); var faces = new[] { new[] { c3, c2, c1 }, new[] { c3, c1, c4 }, new[] { c2, c3, c4 }, new[] { c1, c2, c4 } }; 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; }
public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture) { var numsides = (int) _numSides.GetValue(); if (numsides < 3) yield break; // This is all very similar to the cylinder brush. var width = box.Width; var length = box.Length; var major = width / 2; var minor = length / 2; var angle = 2 * DMath.PI / numsides; var points = new Coordinate[numsides]; for (var i = 0; i < numsides; i++) { var a = i * angle; var xval = box.Center.X + major * DMath.Cos(a); var yval = box.Center.Y + minor * DMath.Sin(a); var zval = box.Start.Z; points[i] = new Coordinate(xval, yval, zval).Round(0); } var faces = new List<Coordinate[]>(); var point = new Coordinate(box.Center.X, box.Center.Y, box.End.Z); for (var i = 0; i < numsides; i++) { var next = (i + 1) % numsides; faces.Add(new[] {points[i], point, points[next]}); } faces.Add(points.ToArray()); 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; }
public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var solid = new Solid(generator.GetNextObjectID()) { Colour = Colour.GetRandomBrushColour() }; foreach (var arr in box.GetBoxFaces()) { 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.Round(roundDecimals), face))); face.UpdateBoundingBox(); face.AlignTextureToFace(); solid.Faces.Add(face); } solid.UpdateBoundingBox(); yield return solid; }
public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var numsides = (int) _numSides.GetValue(); if (numsides < 3) yield break; // Cylinders can be elliptical so use both major and minor rather than just the radius // NOTE: when a low number (< 10ish) of faces are selected this will cause the cylinder to not touch all the edges of the box. var width = box.Width; var length = box.Length; var height = box.Height; var major = width / 2; var minor = length / 2; var angle = 2 * DMath.PI / numsides; // Calculate the X and Y points for the ellipse var points = new Coordinate[numsides]; for (var i = 0; i < numsides; i++) { var a = i * angle; var xval = box.Center.X + major * DMath.Cos(a); var yval = box.Center.Y + minor * DMath.Sin(a); var zval = box.Start.Z; points[i] = new Coordinate(xval, yval, zval).Round(roundDecimals); } var faces = new List<Coordinate[]>(); // Add the vertical faces var z = new Coordinate(0, 0, height).Round(roundDecimals); for (var i = 0; i < numsides; i++) { var next = (i + 1) % numsides; faces.Add(new[] {points[i], points[i] + z, points[next] + z, points[next]}); } // Add the elliptical 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 Solid MakeSolid(IDGenerator generator, IEnumerable<Coordinate[]> faces, ITexture texture, Color col) { var solid = new Solid(generator.GetNextObjectID()) { Colour = col }; 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(); return solid; }
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 Face ReadFace(string line, IDGenerator generator) { const NumberStyles ns = NumberStyles.Float; var parts = line.Split(' ').Where(x => !String.IsNullOrWhiteSpace(x)).ToList(); Assert(parts[0] == "("); Assert(parts[4] == ")"); Assert(parts[5] == "("); Assert(parts[9] == ")"); Assert(parts[10] == "("); Assert(parts[14] == ")"); var face = new Face(generator.GetNextFaceID()) { Plane = new Plane(Coordinate.Parse(parts[1], parts[2], parts[3]), Coordinate.Parse(parts[6], parts[7], parts[8]), Coordinate.Parse(parts[11], parts[12], parts[13])), Texture = {Name = parts[15]} }; // Cater for older-style map formats if (parts.Count == 21) { face.AlignTextureToFace(); face.Texture.XShift = decimal.Parse(parts[16], ns, CultureInfo.InvariantCulture); face.Texture.YShift = decimal.Parse(parts[17], ns, CultureInfo.InvariantCulture); face.Texture.Rotation = decimal.Parse(parts[18], ns, CultureInfo.InvariantCulture); face.Texture.XScale = decimal.Parse(parts[19], ns, CultureInfo.InvariantCulture); face.Texture.YScale = decimal.Parse(parts[20], ns, CultureInfo.InvariantCulture); } else { Assert(parts[16] == "["); Assert(parts[21] == "]"); Assert(parts[22] == "["); Assert(parts[27] == "]"); face.Texture.UAxis = Coordinate.Parse(parts[17], parts[18], parts[19]); face.Texture.XShift = decimal.Parse(parts[20], ns, CultureInfo.InvariantCulture); face.Texture.VAxis = Coordinate.Parse(parts[23], parts[24], parts[25]); face.Texture.YShift = decimal.Parse(parts[26], ns, CultureInfo.InvariantCulture); face.Texture.Rotation = decimal.Parse(parts[28], ns, CultureInfo.InvariantCulture); face.Texture.XScale = decimal.Parse(parts[29], ns, CultureInfo.InvariantCulture); face.Texture.YScale = decimal.Parse(parts[30], ns, CultureInfo.InvariantCulture); } return face; }
private void PokeFace(Face face, int num) { var solid = face.Parent; // Remove the face solid.Faces.Remove(face); face.Parent = null; _selection.Remove(face); var center = face.BoundingBox.Center + face.Plane.Normal * num; foreach (var edge in face.GetEdges()) { var v1 = face.Vertices.First(x => x.Location == edge.Start); var v2 = face.Vertices.First(x => x.Location == edge.End); var verts = new[] { v1.Location, v2.Location, center }; var f = new Face(Document.Map.IDGenerator.GetNextFaceID()) { Parent = solid, Plane = new Plane(verts[0], verts[1], verts[2]), Colour = solid.Colour, Texture = face.Texture.Clone() }; f.Vertices.AddRange(verts.Select(x => new Vertex(x, face))); f.UpdateBoundingBox(); f.AlignTextureToFace(); solid.Faces.Add(f); _selection.Add(f); } solid.UpdateBoundingBox(); UpdateSelection(); MainTool.SetDirty(true, true); }
private void BevelFace(Face face, int num) { var solid = face.Parent; var vertexCoordinates = face.Vertices.ToDictionary(x => x, x => x.Location); // Scale the face a bit and move it away by the bevel distance face.Transform(new UnitScale(Coordinate.One * 0.9m, face.BoundingBox.Center), TransformFlags.TextureLock); face.Transform(new UnitTranslate(face.Plane.Normal * num), TransformFlags.TextureLock); foreach (var edge in face.GetEdges()) { var v1 = face.Vertices.First(x => x.Location == edge.Start); var v2 = face.Vertices.First(x => x.Location == edge.End); var verts = new[] { vertexCoordinates[v1], vertexCoordinates[v2], v2.Location, v1.Location }; var f = new Face(Document.Map.IDGenerator.GetNextFaceID()) { Parent = solid, Plane = new Plane(verts[0], verts[1], verts[2]), Colour = solid.Colour, Texture = face.Texture.Clone() }; f.Vertices.AddRange(verts.Select(x => new Vertex(x, face))); f.UpdateBoundingBox(); f.AlignTextureToFace(); solid.Faces.Add(f); _selection.Add(f); } solid.UpdateBoundingBox(); UpdateSelection(); MainTool.SetDirty(true, true); }