public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) yield break; var width = box.Width; var length = box.Length; var height = box.Height; var major = width / 2; var minor = length / 2; var heightRadius = height / 2; var angleV = DMath.DegreesToRadians(180) / numSides; var angleH = DMath.DegreesToRadians(360) / numSides; var faces = new List<Coordinate[]>(); var bottom = new Coordinate(box.Center.X, box.Center.Y, box.Start.Z).Round(roundDecimals); var top = new Coordinate(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals); for (var i = 0; i < numSides; i++) { // Top -> bottom var zAngleStart = angleV * i; var zAngleEnd = angleV * (i + 1); var zStart = heightRadius * DMath.Cos(zAngleStart); var zEnd = heightRadius * DMath.Cos(zAngleEnd); var zMultStart = DMath.Sin(zAngleStart); var zMultEnd = DMath.Sin(zAngleEnd); for (var j = 0; j < numSides; j++) { // Go around the circle in X/Y var xyAngleStart = angleH * j; var xyAngleEnd = angleH * ((j + 1) % numSides); var xyStartX = major * DMath.Cos(xyAngleStart); var xyStartY = minor * DMath.Sin(xyAngleStart); var xyEndX = major * DMath.Cos(xyAngleEnd); var xyEndY = minor * DMath.Sin(xyAngleEnd); var one = (new Coordinate(xyStartX * zMultStart, xyStartY * zMultStart, zStart) + box.Center).Round(roundDecimals); var two = (new Coordinate(xyEndX * zMultStart, xyEndY * zMultStart, zStart) + box.Center).Round(roundDecimals); var three = (new Coordinate(xyEndX * zMultEnd, xyEndY * zMultEnd, zEnd) + box.Center).Round(roundDecimals); var four = (new Coordinate(xyStartX * zMultEnd, xyStartY * zMultEnd, zEnd) + box.Center).Round(roundDecimals); if (i == 0) { // Top faces are triangles faces.Add(new[] { top, three, four }); } else if (i == numSides - 1) { // Bottom faces are also triangles faces.Add(new[] { bottom, one, two }); } else { // Inner faces are quads faces.Add(new[] { one, two, three, four }); } } } yield return MakeSolid(generator, faces, texture, Colour.GetRandomBrushColour()); }
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 PasteSpecialDialog(Box source) { _source = source; InitializeComponent(); EntityPrefix.Enabled = PrefixEntityNamesCheckbox.Checked; ZeroOffsetXButton.Click += (sender, e) => OffsetX.Value = 0; ZeroOffsetYButton.Click += (sender, e) => OffsetY.Value = 0; ZeroOffsetZButton.Click += (sender, e) => OffsetZ.Value = 0; SourceOffsetXButton.Click += (sender, e) => OffsetX.Value = _source.Width; SourceOffsetYButton.Click += (sender, e) => OffsetY.Value = _source.Length; SourceOffsetZButton.Click += (sender, e) => OffsetZ.Value = _source.Height; ZeroRotationXButton.Click += (sender, e) => RotationX.Value = 0; ZeroRotationYButton.Click += (sender, e) => RotationY.Value = 0; ZeroRotationZButton.Click += (sender, e) => RotationZ.Value = 0; PrefixEntityNamesCheckbox.CheckedChanged += (sender, e) => EntityPrefix.Enabled = PrefixEntityNamesCheckbox.Checked; NumCopies.Value = _lastNumCopies; OffsetX.Value = _lastXOffset; OffsetY.Value = _lastYOffset; OffsetZ.Value = _lastZOffset; RotationX.Value = _lastXRotation; RotationY.Value = _lastYRotation; RotationZ.Value = _lastZRotation; }
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; }
private decimal Extractor(Box box) { Coordinate coord; switch (_direction) { case AlignDirection.Min: coord = box.Start; break; case AlignDirection.Max: coord = box.End; break; default: throw new ArgumentOutOfRangeException(); } switch (_axis) { case AlignAxis.X: return coord.X; case AlignAxis.Y: return coord.Y; case AlignAxis.Z: return coord.Z; default: throw new ArgumentOutOfRangeException(); } }
public AlignObjectsEditOperation(Box alignBox, AlignAxis axis, AlignDirection direction, TransformFlags transformFlags) { _alignBox = alignBox; _axis = axis; _direction = direction; _transformFlags = transformFlags; }
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; }
public Map() { Version = 1; Visgroups = new List<Visgroup>(); Cameras = new List<Camera>(); ActiveCamera = null; IDGenerator = new IDGenerator(); WorldSpawn = new World(IDGenerator.GetNextObjectID()); Show2DGrid = SnapToGrid = true; TextureLock = true; HideDisplacementSolids = true; CordonBounds = new Box(Coordinate.One * -1024, Coordinate.One * 1024); }
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) { var wallWidth = (int) _width.GetValue(); if (wallWidth < 1) yield break; var numsides = (int) _numSides.GetValue(); if (numsides < 3) yield break; // Very similar to the cylinder, except we have multiple solids this time var width = box.Width; var length = box.Length; var height = box.Height; var majorOut = width / 2; var majorIn = majorOut - wallWidth; var minorOut = length / 2; var minorIn = minorOut - wallWidth; var angle = 2 * DMath.PI / numsides; var colour = Colour.GetRandomBrushColour(); // Calculate the X and Y points for the inner and outer ellipses var outer = new Coordinate[numsides]; var inner = new Coordinate[numsides]; for (var i = 0; i < numsides; i++) { var a = i * angle; var xval = box.Center.X + majorOut * DMath.Cos(a); var yval = box.Center.Y + minorOut * DMath.Sin(a); var zval = box.Start.Z; outer[i] = new Coordinate(xval, yval, zval).Round(0); xval = box.Center.X + majorIn * DMath.Cos(a); yval = box.Center.Y + minorIn * DMath.Sin(a); inner[i] = new Coordinate(xval, yval, zval).Round(0); } // Create the solids var z = new Coordinate(0, 0, height); for (var i = 0; i < numsides; i++) { var faces = new List<Coordinate[]>(); var next = (i + 1) % numsides; faces.Add(new[] { outer[i], outer[i] + z, outer[next] + z, outer[next] }); faces.Add(new[] { inner[next], inner[next] + z, inner[i] + z, inner[i] }); faces.Add(new[] { outer[next], outer[next] + z, inner[next] + z, inner[next] }); faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] }); faces.Add(new[] { inner[next] + z, outer[next] + z, outer[i] + z, inner[i] + z }); faces.Add(new[] { inner[i], outer[i], outer[next], inner[next] }); yield return MakeSolid(generator, faces, texture, colour); } }
public TransformDialog(Box source) { _source = source; InitializeComponent(); ZeroValueXButton.Click += (sender, e) => ValueX.Value = zeroValue; ZeroValueYButton.Click += (sender, e) => ValueY.Value = zeroValue; ZeroValueZButton.Click += (sender, e) => ValueZ.Value = zeroValue; SourceValueXButton.Click += (sender, e) => ValueX.Value = _source.Width; SourceValueYButton.Click += (sender, e) => ValueY.Value = _source.Length; SourceValueZButton.Click += (sender, e) => ValueZ.Value = _source.Height; TypeChanged(null, null); }
public Cloud(IEnumerable<Coordinate> points) { Points = new List<Coordinate>(points); BoundingBox = new Box(points); MinX = MinY = MinZ = MaxX = MaxY = MaxZ = null; foreach (var p in points) { if (MinX == null || p.X < MinX.X) MinX = p; if (MinY == null || p.Y < MinY.Y) MinY = p; if (MinZ == null || p.Z < MinZ.Z) MinZ = p; if (MaxX == null || p.X > MaxX.X) MaxX = p; if (MaxY == null || p.Y > MaxY.Y) MaxY = p; if (MaxZ == null || p.Z > MaxZ.Z) MaxZ = p; } }
public void CopyEntityTest() { var idGen = new IDGenerator(); var box = new Box(Coordinate.One * -100, Coordinate.One * 100); // Create an entity with children var ent = new Entity(idGen.GetNextObjectID()); ent.EntityData.Name = "Test"; ent.EntityData.Properties.Add(new Property { Key = "key1", Value = "value1"}); ent.EntityData.Properties.Add(new Property { Key = "key2", Value = "value2"}); ent.EntityData.Flags = 12345; var solids = new BlockBrush().Create(idGen, box, null, 0); foreach (var mo in solids) mo.SetParent(ent); // Copy and reconstruct var gs = VmfProvider.CreateCopyStream(new List<MapObject> {ent}); var pasted = VmfProvider.ExtractCopyStream(gs, idGen).ToList(); // Test object Assert.AreEqual(1, pasted.Count); Assert.IsInstanceOfType(pasted[0], typeof(Entity)); // Test entity var pastedEnt = (Entity) pasted[0]; Assert.AreEqual("Test", pastedEnt.EntityData.Name); Assert.AreEqual(12345, pastedEnt.EntityData.Flags); // Test properties Assert.AreEqual(2, pastedEnt.EntityData.Properties.Count); var k1 = pastedEnt.EntityData.Properties.FirstOrDefault(x => x.Key == "key1"); var k2 = pastedEnt.EntityData.Properties.FirstOrDefault(x => x.Key == "key1"); Assert.IsNotNull(k1); Assert.IsNotNull(k2); Assert.AreEqual(k1.Value, "value1"); Assert.AreEqual(k2.Value, "value1"); // Test child Assert.AreEqual(1, pastedEnt.ChildCount); Assert.IsInstanceOfType(pastedEnt.GetChildren().ToList()[0], typeof(Solid)); // Check number of sides, values of sides not so important var pastedSolid = (Solid) pastedEnt.GetChildren().ToList()[0]; Assert.AreEqual(6, pastedSolid.Faces.Count); }
public override void BoxDrawnConfirm(ViewportBase viewport) { var box = new Box(State.BoxStart, State.BoxEnd); if (box.Start.X != box.End.X && box.Start.Y != box.End.Y && box.Start.Z != box.End.Z) { CreateBrush(box); _lastBox = box; } _preview = null; base.BoxDrawnConfirm(viewport); if (Select.SwitchToSelectAfterCreation) { Mediator.Publish(HotkeysMediator.SwitchTool, HotkeyTool.Selection); } if (Select.ResetBrushTypeOnCreation) { Mediator.Publish(EditorMediator.ResetSelectedBrushType); } }
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 void BenchmarkSolidConstruction() { var idg = new IDGenerator(); var box = new Box(Coordinate.One * -100, Coordinate.One * 100); var planes = new CylinderBrush().Create(idg, box, null, 2).OfType<Solid>().SelectMany(x => x.Faces).Select(x => x.Plane).ToList(); var stopwatch = new Stopwatch(); stopwatch.Start(); for (var b = 0; b < 1000; b++) { Solid.CreateFromIntersectingPlanes(planes, idg); } stopwatch.Stop(); Debug.WriteLine(stopwatch.Elapsed); stopwatch.Restart(); for (var b = 0; b < 1000; b++) { var polys = new List<Polygon>(); for (var i = 0; i < planes.Count; i++) { var poly = new Polygon(planes[i]); for (var j = 0; j < planes.Count; j++) { if (i != j) poly.Split(planes[j]); } polys.Add(poly); } var solid = new Solid(idg.GetNextObjectID()); foreach (var polygon in polys) { var face = new Face(idg.GetNextFaceID()) {Plane = polygon.Plane}; face.Vertices.AddRange(polygon.Vertices.Select(x => new Vertex(x, face))); face.UpdateBoundingBox(); face.AlignTextureToWorld(); solid.Faces.Add(face); } solid.UpdateBoundingBox(); } stopwatch.Stop(); Debug.WriteLine(stopwatch.Elapsed); }
public override void MouseMove(ViewportBase viewport, ViewportEvent e) { var vp = viewport as Viewport3D; if (vp == null) return; UpdateCurrentFace(vp, e); switch (_state) { case SketchState.None: case SketchState.Ready: // face detect break; case SketchState.DrawingBase: _drawing = new Box(_drawing.Start, _intersection); break; case SketchState.DrawingVolume: _drawing = new Box(_drawing.Start, _intersection); break; default: throw new ArgumentOutOfRangeException(); } }
public override void BoxDrawnCancel(ViewportBase viewport) { _lastBox = new Box(State.BoxStart, State.BoxEnd); _preview = null; base.BoxDrawnCancel(viewport); }
private MapObject GetBrush(Box bounds, IDGenerator idg) { var brush = BrushManager.CurrentBrush; var ti = Document.TextureCollection.SelectedTexture; var texture = ti != null ? ti.GetTexture() : null; var created = brush.Create(idg, bounds, texture, BrushManager.RoundCreatedVertices ? 0 : 2).ToList(); if (created.Count > 1) { var g = new Group(idg.GetNextObjectID()); created.ForEach(x => x.SetParent(g)); g.UpdateBoundingBox(); return g; } return created.FirstOrDefault(); }
private void CreateBrush(Box bounds) { var brush = GetBrush(bounds, Document.Map.IDGenerator); if (brush == null) return; brush.IsSelected = Select.SelectCreatedBrush; IAction action = new Create(Document.Map.WorldSpawn.ID, brush); if (Select.SelectCreatedBrush && Select.DeselectOthersWhenSelectingCreation) { action = new ActionCollection(new ChangeSelection(new MapObject[0], Document.Selection.GetSelectedObjects()), action); } Document.PerformAction("Create " + BrushManager.CurrentBrush.Name.ToLower(), action); }
public override void UpdateFrame(ViewportBase viewport, FrameInfo frame) { if (_updatePreview && ShouldDrawBox(viewport)) { var box = new Box(State.BoxStart, State.BoxEnd); var brush = GetBrush(box, new IDGenerator()); _preview = new List<Face>(); CollectFaces(_preview, new[] { brush }); var color = GetRenderBoxColour(); _preview.ForEach(x => { x.Colour = color; }); } _updatePreview = false; }
public override void ToolSelected(bool preventHistory) { BrushManager.ValuesChanged += ValuesChanged; var sel = Document.Selection.GetSelectedObjects().OfType<Solid>().ToList(); if (sel.Any()) { _lastBox = new Box(sel.Select(x => x.BoundingBox)); } else if (_lastBox == null) { var gs = Document.Map.GridSpacing; _lastBox = new Box(Coordinate.Zero, new Coordinate(gs, gs, gs)); } _updatePreview = true; }
public override void UpdateBoundingBox() { var list = new List<Coordinate>(); // LINQ doesn't seem to like multi-dimensional arrays foreach (var p in Points) list.Add(p.CurrentPosition.Location); BoundingBox = new Box(list); }
private MapObject SelectionTest(Viewport2D viewport, ViewportEvent e) { // Create a box to represent the click, with a tolerance level var unused = viewport.GetUnusedCoordinate(new Coordinate(100000, 100000, 100000)); var tolerance = 4 / viewport.Zoom; // Selection tolerance of four pixels var used = viewport.Expand(new Coordinate(tolerance, tolerance, 0)); var add = used + unused; var click = viewport.Expand(viewport.ScreenToWorld(e.X, viewport.Height - e.Y)); var box = new Box(click - add, click + add); var centerHandles = Sledge.Settings.Select.DrawCenterHandles; var centerOnly = Sledge.Settings.Select.ClickSelectByCenterHandlesOnly; // Get the first element that intersects with the box, selecting or deselecting as needed return Document.Map.WorldSpawn.GetAllNodesIntersecting2DLineTest(box, centerHandles, centerOnly).FirstOrDefault(); }
private void RenderTransformBox(Viewport2D viewport) { if (!CurrentTransform.HasValue) return; var box = new Box(State.PreTransformBoxStart, State.PreTransformBoxEnd); var trans = CreateMatrixMultTransformation(CurrentTransform.Value); box = box.Transform(trans); var s = viewport.Flatten(box.Start); var e = viewport.Flatten(box.End); GL.Enable(EnableCap.LineStipple); GL.LineStipple(10, 0xAAAA); GL.Begin(PrimitiveType.Lines); GL.Color4(Color.FromArgb(64, BoxColour)); Coord(s.DX, s.DY, e.DZ); Coord(e.DX, s.DY, e.DZ); Coord(s.DX, e.DY, e.DZ); Coord(e.DX, e.DY, e.DZ); Coord(s.DX, s.DY, e.DZ); Coord(s.DX, e.DY, e.DZ); Coord(e.DX, s.DY, e.DZ); Coord(e.DX, e.DY, e.DZ); GL.End(); GL.Disable(EnableCap.LineStipple); RenderBoxText(viewport, s, e); }
protected override void MouseDraggingToResize(Viewport2D viewport, ViewportEvent e) { if (_currentTool == null) { base.MouseDraggingToResize(viewport, e); return; } State.Action = BoxAction.Resizing; CurrentTransform = GetTransformMatrix(viewport, e); if (CurrentTransform.HasValue) { Document.SetSelectListTransform(CurrentTransform.Value); var box = new Box(State.PreTransformBoxStart, State.PreTransformBoxEnd); var trans = CreateMatrixMultTransformation(CurrentTransform.Value); Mediator.Publish(EditorMediator.SelectionBoxChanged, box.Transform(trans)); } else { //OnBoxChanged(); } }
public IEnumerable<MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) yield break; var wallWidth = _wallWidth.GetValue(); if (wallWidth < 1) yield break; var arc = _arc.GetValue(); if (arc < 1) yield break; var startAngle = _startAngle.GetValue(); if (startAngle < 0 || startAngle > 359) yield break; var addHeight = _addHeight.GetValue(); var curvedRamp = _curvedRamp.GetValue(); var tiltAngle = curvedRamp ? _tiltAngle.GetValue() : 0; if (DMath.Abs(tiltAngle % 180) == 90) yield break; var tiltInterp = curvedRamp && _tiltInterp.GetValue(); // Very similar to the pipe brush, except with options for start angle, arc, height and tilt var width = box.Width; var length = box.Length; var height = box.Height; var majorOut = width / 2; var majorIn = majorOut - wallWidth; var minorOut = length / 2; var minorIn = minorOut - wallWidth; var start = DMath.DegreesToRadians(startAngle); var tilt = DMath.DegreesToRadians(tiltAngle); var angle = DMath.DegreesToRadians(arc) / numSides; var colour = Colour.GetRandomBrushColour(); // Calculate the coordinates of the inner and outer ellipses' points var outer = new Coordinate[numSides + 1]; var inner = new Coordinate[numSides + 1]; for (var i = 0; i < numSides + 1; i++) { var a = start + i * angle; var h = i * addHeight; var interp = tiltInterp ? DMath.Cos(DMath.PI / numSides * (i - numSides / 2M)) : 1; var tiltHeight = wallWidth / 2 * interp * DMath.Tan(tilt); var xval = box.Center.X + majorOut * DMath.Cos(a); var yval = box.Center.Y + minorOut * DMath.Sin(a); var zval = box.Start.Z + (curvedRamp ? h + tiltHeight : 0); outer[i] = new Coordinate(xval, yval, zval).Round(roundDecimals); xval = box.Center.X + majorIn * DMath.Cos(a); yval = box.Center.Y + minorIn * DMath.Sin(a); zval = box.Start.Z + (curvedRamp ? h - tiltHeight : 0); inner[i] = new Coordinate(xval, yval, zval).Round(roundDecimals); } // Create the solids for (var i = 0; i < numSides; i++) { var faces = new List<Coordinate[]>(); var z = new Coordinate(0, 0, height).Round(roundDecimals); // Since we are triangulating/splitting each arch segment, we need to generate 2 brushes per side if (curvedRamp) { // The splitting orientation depends on the curving direction of the arch if (addHeight >= 0) { faces.Add(new[] { outer[i], outer[i] + z, outer[i+1] + z, outer[i+1] }); faces.Add(new[] { outer[i+1], outer[i+1] + z, inner[i] + z, inner[i] }); faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] }); faces.Add(new[] { outer[i] + z, inner[i] + z, outer[i+1] + z }); faces.Add(new[] { outer[i+1], inner[i], outer[i] }); } else { faces.Add(new[] { inner[i+1], inner[i+1] + z, inner[i] + z, inner[i] }); faces.Add(new[] { outer[i], outer[i] + z, inner[i+1] + z, inner[i+1] }); faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] }); faces.Add(new[] { inner[i+1] + z, outer[i] + z, inner[i] + z }); faces.Add(new[] { inner[i], outer[i], inner[i+1] }); } yield return MakeSolid(generator, faces, texture, colour); faces.Clear(); if (addHeight >= 0) { faces.Add(new[] { inner[i+1], inner[i+1] + z, inner[i] + z, inner[i] }); faces.Add(new[] { inner[i], inner[i] + z, outer[i+1] + z, outer[i+1] }); faces.Add(new[] { outer[i+1], outer[i+1] + z, inner[i+1] + z, inner[i+1] }); faces.Add(new[] { inner[i+1] + z, outer[i+1] + z, inner[i] + z }); faces.Add(new[] { inner[i], outer[i+1], inner[i+1] }); } else { faces.Add(new[] { outer[i], outer[i] + z, outer[i+1] + z, outer[i+1] }); faces.Add(new[] { inner[i+1], inner[i+1] + z, outer[i] + z, outer[i] }); faces.Add(new[] { outer[i+1], outer[i+1] + z, inner[i+1] + z, inner[i+1] }); faces.Add(new[] { outer[i] + z, inner[i+1] + z, outer[i+1] + z }); faces.Add(new[] { outer[i+1], inner[i+1], outer[i] }); } yield return MakeSolid(generator, faces, texture, colour); } else { var h = i * addHeight * Coordinate.UnitZ; faces.Add(new[] { outer[i], outer[i] + z, outer[i+1] + z, outer[i+1] }.Select(x => x + h).ToArray()); faces.Add(new[] { inner[i+1], inner[i+1] + z, inner[i] + z, inner[i] }.Select(x => x + h).ToArray()); faces.Add(new[] { outer[i+1], outer[i+1] + z, inner[i+1] + z, inner[i+1] }.Select(x => x + h).ToArray()); faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] }.Select(x => x + h).ToArray()); faces.Add(new[] { inner[i+1] + z, outer[i+1] + z, outer[i] + z, inner[i] + z }.Select(x => x + h).ToArray()); faces.Add(new[] { inner[i], outer[i], outer[i+1], inner[i+1] }.Select(x => x + h).ToArray()); yield return MakeSolid(generator, faces, texture, colour); } } }
public override void UpdateBoundingBox(bool cascadeToParent = true) { BoundingBox = new Box(Faces.Select(x => x.BoundingBox)); base.UpdateBoundingBox(cascadeToParent); }
public override void ToolSelected(bool preventHistory) { _state = SketchState.None; _currentFace = _cloneFace = null; _intersection = null; _drawing = null; _volumePlane = null; }
public override void MouseDown(ViewportBase viewport, ViewportEvent e) { // switch (_state) { case SketchState.None: // nothin break; case SketchState.Ready: if (e.Button != MouseButtons.Left) break; _drawing = new Box(_intersection, _intersection); _state = SketchState.DrawingBase; break; case SketchState.DrawingBase: if (e.Button == MouseButtons.Right) { // Cancel _state = SketchState.None; _drawing = null; } else if (e.Button == MouseButtons.Left) { _drawing = new Box(_drawing.Start, _intersection); _volumePlane = new Plane(new Coordinate(_drawing.End.X, _drawing.Start.Y, _drawing.Start.Z), _drawing.End, _drawing.End + _currentFace.Plane.Normal); _state = SketchState.DrawingVolume; } break; case SketchState.DrawingVolume: if (e.Button == MouseButtons.Right) { _state = SketchState.DrawingBase; _volumePlane = null; } else if (e.Button == MouseButtons.Left) { CreateBrush(new Box(new[] {_drawing.Start, _drawing.End})); _drawing = null; _volumePlane = null; _state = SketchState.None; } break; default: throw new ArgumentOutOfRangeException(); } }