diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bb13d1a3..772ded7cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,10 @@ - `GeometricElement.Intersects` method now supports multiple representations. - `GltfExtensions.ToGlTF` creates parent node for element and child nodes for representation instances. + +### Removed +- `Elements.Doors` class + ## 2.0.0 ### Added diff --git a/Elements.Serialization.IFC/src/IFCElementExtensions.cs b/Elements.Serialization.IFC/src/IFCElementExtensions.cs index 063fdcdc9..691dcda3b 100644 --- a/Elements.Serialization.IFC/src/IFCElementExtensions.cs +++ b/Elements.Serialization.IFC/src/IFCElementExtensions.cs @@ -264,57 +264,6 @@ private static IfcOpeningElement ToIfc(this Opening opening, Guid id, IfcLocalPl return ifcOpening; } - private static IfcDoor ToIfc(this Door door, Guid id, IfcLocalPlacement localPlacement, IfcProductDefinitionShape shape) - { - var ifcDoor = new IfcDoor(IfcGuid.ToIfcGuid(id), - null, - CreateIfcSafeLabelString(door.Name), - null, - null, - localPlacement, - shape, - null, - new IfcPositiveLengthMeasure(new IfcLengthMeasure(door.DoorHeight)), - new IfcPositiveLengthMeasure(new IfcLengthMeasure(door.DoorWidth)), - IfcDoorTypeEnum.DOOR, - door.GetIfcDoorTypeOperation(), - null - ); - - return ifcDoor; - } - - private static IfcDoorTypeOperationEnum GetIfcDoorTypeOperation(this Door door) - { - if (door.OpeningType == DoorOpeningType.SingleSwing) - { - switch (door.OpeningSide) - { - case DoorOpeningSide.LeftHand: - return IfcDoorTypeOperationEnum.SINGLE_SWING_LEFT; - case DoorOpeningSide.RightHand: - return IfcDoorTypeOperationEnum.SINGLE_SWING_RIGHT; - case DoorOpeningSide.DoubleDoor: - return IfcDoorTypeOperationEnum.DOUBLE_DOOR_SINGLE_SWING; - } - } - else if (door.OpeningType == DoorOpeningType.DoubleSwing) - { - switch (door.OpeningSide) - { - case DoorOpeningSide.LeftHand: - return IfcDoorTypeOperationEnum.DOUBLE_SWING_LEFT; - case DoorOpeningSide.RightHand: - return IfcDoorTypeOperationEnum.DOUBLE_SWING_RIGHT; - case DoorOpeningSide.DoubleDoor: - return IfcDoorTypeOperationEnum.DOUBLE_DOOR_DOUBLE_SWING; - } - } - - - return IfcDoorTypeOperationEnum.NOTDEFINED; - } - internal static IfcLocalPlacement ToIfcLocalPlacement(this Transform transform, Document doc, IfcObjectPlacement parent = null) { var placement = transform.ToIfcAxis2Placement3D(doc); @@ -404,10 +353,6 @@ private static IfcProduct ConvertElementToIfcProduct(Guid id, GeometricElement e { e = floor.ToIfc(id, localPlacement, shape); } - else if (element is Door door) - { - e = door.ToIfc(id, localPlacement, shape); - } else if (element is Space space) { e = space.ToIfc(id, localPlacement, shape); diff --git a/Elements.Serialization.IFC/src/IFCToHypar/Converters/CompositeFromIfcProductConverter.cs b/Elements.Serialization.IFC/src/IFCToHypar/Converters/CompositeFromIfcProductConverter.cs index f85b4a955..6e5c7ff2a 100644 --- a/Elements.Serialization.IFC/src/IFCToHypar/Converters/CompositeFromIfcProductConverter.cs +++ b/Elements.Serialization.IFC/src/IFCToHypar/Converters/CompositeFromIfcProductConverter.cs @@ -38,7 +38,7 @@ public CompositeFromIfcProductConverter(List converter public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationData representationData, List constructionErrors) { GeometricElement result; - + foreach (var converter in _converters) { if (!converter.CanConvert(ifcProduct)) diff --git a/Elements.Serialization.IFC/src/IFCToHypar/Converters/FromIfcDoorConverter.cs b/Elements.Serialization.IFC/src/IFCToHypar/Converters/FromIfcDoorConverter.cs deleted file mode 100644 index ab190b5c6..000000000 --- a/Elements.Serialization.IFC/src/IFCToHypar/Converters/FromIfcDoorConverter.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Elements.Geometry; -using Elements.Serialization.IFC.IFCToHypar.RepresentationsExtraction; -using Elements; -using IFC; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Elements.Serialization.IFC.IFCToHypar.Converters -{ - internal class FromIfcDoorConverter : IFromIfcProductConverter - { - public GeometricElement ConvertToElement(IfcProduct ifcProduct, RepresentationData repData, List constructionErrors) - { - if (!(ifcProduct is IfcDoor ifcDoor)) - { - return null; - } - - if (ifcDoor.PredefinedType != IfcDoorTypeEnum.DOOR) - { - constructionErrors.Add($"#{ifcProduct.StepId}: Doors of type {ifcDoor.PredefinedType} are not supported yet."); - return null; - } - - var openingSide = ifcDoor.GetDoorOpeningSide(); - var openingType = ifcDoor.GetDoorOpeningType(); - - if (openingSide == DoorOpeningSide.Undefined || openingType == DoorOpeningType.Undefined) - { - constructionErrors.Add($"#{ifcProduct.StepId}: Doors of operation type {ifcDoor.OperationType} are not supported yet."); - return null; - } - - // TODO: Implement during the connections establishment. - //var wall = GetWallFromDoor(ifcDoor, allWalls); - var doorWidth = (IfcLengthMeasure)ifcDoor.OverallWidth; - var doorHeight = (IfcLengthMeasure)ifcDoor.OverallHeight; - var doorThickness = Door.DEFAULT_DOOR_THICKNESS; - - var result = new Door(doorWidth, - doorHeight, - doorThickness, - openingSide, - openingType, - repData.Transform, - repData.Material, - new Representation(repData.SolidOperations), - false, - IfcGuid.FromIfcGUID(ifcDoor.GlobalId), - ifcDoor.Name - ); - - return result; - } - - private static Wall GetWallFromDoor(IfcDoor door, List allWalls) - { - var walls = door.Decomposes.Select(rel => rel.RelatingObject).OfType(); - - if (!walls.Any()) - { - return null; - } - - var ifcWall = walls.First(); - var matchingWalls = allWalls.Where(w => w.Id.Equals(IfcGuid.FromIfcGUID(ifcWall.GlobalId))); - - return matchingWalls.FirstOrDefault(); - } - - public bool CanConvert(IfcProduct ifcProduct) - { - return ifcProduct is IfcDoor; - } - } -} diff --git a/Elements.Serialization.IFC/src/IFCToHypar/FromIfcModelProvider.cs b/Elements.Serialization.IFC/src/IFCToHypar/FromIfcModelProvider.cs index f88cddd2d..7ef09425f 100644 --- a/Elements.Serialization.IFC/src/IFCToHypar/FromIfcModelProvider.cs +++ b/Elements.Serialization.IFC/src/IFCToHypar/FromIfcModelProvider.cs @@ -36,7 +36,7 @@ internal class FromIfcModelProvider /// /// A path to IFC file. /// Only IfcProducts with these ids will be converted. - /// An object that converts IfcProducts to GeometricElements. + /// An object that converts IfcProducts to GeometricElements. /// If null, a fallback default converter will be created. /// An object that extracts RepresentationData from IfcRepresentations /// of IfcProduct. If null, a fallback default extractor will be created. @@ -160,7 +160,7 @@ private Element ConvertIfcProductToElement(IfcProduct product) //definition.SkipCSGUnion = true; } - // The cartesian transform needs to be applied + // The cartesian transform needs to be applied // before the element transformation because it // may contain scale and rotation. var instanceTransform = new Transform(repData.MappingInfo.MappingTransform); @@ -192,13 +192,13 @@ private void HandleRelationships(List elements) .Select(v => v.RelatedOpeningElement).Cast() .SelectMany(io => io.ToOpenings()); - var openingsOwner = (IHasOpenings) elementWithOpenings; + var openingsOwner = (IHasOpenings)elementWithOpenings; openingsOwner.Openings.AddRange(openings); } } /// - /// Create the default IFromIfcProductConverter. It will be used, if + /// Create the default IFromIfcProductConverter. It will be used, if /// IFromIfcProductConverter is not specified in the constructor. /// private static IFromIfcProductConverter GetDefaultFromIfcConverter() @@ -208,7 +208,6 @@ private static IFromIfcProductConverter GetDefaultFromIfcConverter() new FromIfcFloorConverter(), new FromIfcSpaceConverter(), new FromIfcWallConverter(), - new FromIfcDoorConverter(), new FromIfcBeamConverter(), new FromIfcColumnConverter() }; @@ -219,7 +218,7 @@ private static IFromIfcProductConverter GetDefaultFromIfcConverter() } /// - /// Create the default IfcRepresentationDataExtractor. It will be used, if + /// Create the default IfcRepresentationDataExtractor. It will be used, if /// IfcRepresentationDataExtractor is not specified in the constructor. /// private static IfcRepresentationDataExtractor GetDefaultRepresentationDataExtractor(MaterialExtractor materialExtractor) diff --git a/Elements.Serialization.IFC/src/IFCToHypar/IFCExtensions.cs b/Elements.Serialization.IFC/src/IFCToHypar/IFCExtensions.cs index 63e52c2f1..c57fc8d7d 100644 --- a/Elements.Serialization.IFC/src/IFCToHypar/IFCExtensions.cs +++ b/Elements.Serialization.IFC/src/IFCToHypar/IFCExtensions.cs @@ -14,39 +14,6 @@ namespace Elements.Serialization.IFC.IFCToHypar /// internal static class IFCExtensions { - internal static DoorOpeningSide GetDoorOpeningSide(this IfcDoor ifcDoor) - { - switch (ifcDoor.OperationType) - { - case IfcDoorTypeOperationEnum.SINGLE_SWING_LEFT: - case IfcDoorTypeOperationEnum.DOUBLE_SWING_LEFT: - return DoorOpeningSide.LeftHand; - case IfcDoorTypeOperationEnum.SINGLE_SWING_RIGHT: - case IfcDoorTypeOperationEnum.DOUBLE_SWING_RIGHT: - return DoorOpeningSide.RightHand; - case IfcDoorTypeOperationEnum.DOUBLE_DOOR_SINGLE_SWING: - case IfcDoorTypeOperationEnum.DOUBLE_DOOR_DOUBLE_SWING: - return DoorOpeningSide.DoubleDoor; - } - return DoorOpeningSide.Undefined; - } - - internal static DoorOpeningType GetDoorOpeningType(this IfcDoor ifcDoor) - { - switch (ifcDoor.OperationType) - { - case IfcDoorTypeOperationEnum.SINGLE_SWING_LEFT: - case IfcDoorTypeOperationEnum.SINGLE_SWING_RIGHT: - case IfcDoorTypeOperationEnum.DOUBLE_DOOR_SINGLE_SWING: - return DoorOpeningType.SingleSwing; - case IfcDoorTypeOperationEnum.DOUBLE_SWING_LEFT: - case IfcDoorTypeOperationEnum.DOUBLE_SWING_RIGHT: - case IfcDoorTypeOperationEnum.DOUBLE_DOOR_DOUBLE_SWING: - return DoorOpeningType.DoubleSwing; - } - return DoorOpeningType.Undefined; - } - // TODO: In IFC an IfcOpeningElement may have several extrudes. // Now they are extracted as separate Openings. As the result // initial Guid of IfcOpeningElement is not saved. diff --git a/Elements.Serialization.IFC/test/IFCTests.cs b/Elements.Serialization.IFC/test/IFCTests.cs index cc0900379..b6ef28e06 100644 --- a/Elements.Serialization.IFC/test/IFCTests.cs +++ b/Elements.Serialization.IFC/test/IFCTests.cs @@ -29,7 +29,7 @@ public IfcTests(ITestOutputHelper output) // [InlineData("rac_sample", "../../../models/IFC4/rac_advanced_sample_project.ifc")] // [InlineData("rme_sample", "../../../models/IFC4/rme_advanced_sample_project.ifc")] // [InlineData("rst_sample", "../../../models/IFC4/rst_advanced_sample_project.ifc")] - [InlineData("AC-20-Smiley-West-10-Bldg", "../../../models/IFC4/AC-20-Smiley-West-10-Bldg.ifc", 1972, 120, 530, 270, 9, 140, 10, 2)] + [InlineData("AC-20-Smiley-West-10-Bldg", "../../../models/IFC4/AC-20-Smiley-West-10-Bldg.ifc", 1963, 120, 530, 270, 9, 140, 10, 2)] // TODO: Some walls are extracted incorrectly and intersecting the roof. It happens because // IfcBooleanClippingResultParser doesn't handle the boolean clipping operation. // In order to fix it surface support is required. @@ -39,7 +39,7 @@ public IfcTests(ITestOutputHelper output) // TODO: The entrance door has an incorrect representation. It happens because during // the UpdateRepresentation the default representation of a door is created instead of // the extracted one. - [InlineData("AC20-Institute-Var-2", "../../../models/IFC4/AC20-Institute-Var-2.ifc", 1513, 5, 570, 121, 7, 82, 0, 21)] + [InlineData("AC20-Institute-Var-2", "../../../models/IFC4/AC20-Institute-Var-2.ifc", 1506, 5, 570, 121, 7, 82, 0, 21)] // [InlineData("20160125WestRiverSide Hospital - IFC4-Autodesk_Hospital_Sprinkle", "../../../models/IFC4/20160125WestRiverSide Hospital - IFC4-Autodesk_Hospital_Sprinkle.ifc")] public void FromIFC4(string name, string ifcPath, @@ -58,7 +58,6 @@ int expectedCountOfErrors int countOfFloors = model.AllElementsOfType().Count(); int countOfOpenings = model.AllElementsOfType().Count(); int countOfWalls = model.AllElementsOfType().Count(); - int countOfDoors = model.AllElementsOfType().Count(); int countOfSpaces = model.AllElementsOfType().Count(); int countOfBeams = model.AllElementsOfType().Count(); @@ -67,7 +66,6 @@ int expectedCountOfErrors Assert.Equal(expectedCountOfFloors, countOfFloors); Assert.Equal(expectedCountOfOpenings, countOfOpenings); Assert.Equal(expectedCountOfWalls, countOfWalls); - Assert.Equal(expectedCountOfDoors, countOfDoors); Assert.Equal(expectedCountOfSpaces, countOfSpaces); Assert.Equal(expectedCountOfBeams, countOfBeams); @@ -127,32 +125,6 @@ public void SpaceTemplate() hyparModel.ToIFC(path); } - [Fact] - public void Doors() - { - var model = new Model(); - - // Add 2 walls. - var wallLine1 = new Line(Vector3.Origin, new Vector3(10, 10, 0)); - var wallLine2 = new Line(new Vector3(10, 10, 0), new Vector3(10, 15, 0)); - var wall1 = new StandardWall(wallLine1, 0.2, 3, name: "Wall1"); - var wall2 = new StandardWall(wallLine2, 0.2, 2, name: "Wall2"); - - var door1 = new Door(wallLine1, 0.5, 1.5, 2.0, Door.DEFAULT_DOOR_THICKNESS, DoorOpeningSide.LeftHand, DoorOpeningType.DoubleSwing); - var door2 = new Door(wallLine2, 0.5, 1.5, 1.8, Door.DEFAULT_DOOR_THICKNESS, DoorOpeningSide.LeftHand, DoorOpeningType.DoubleSwing); - - wall1.AddDoorOpening(door1); - wall2.AddDoorOpening(door2); - - model.AddElement(wall1); - model.AddElement(wall2); - model.AddElement(door1); - model.AddElement(door2); - - model.ToJson(ConstructJsonPath("IfcDoor")); - model.ToIFC(ConstructIfcPath("IfcDoor")); - } - [Fact] public void Wall() { diff --git a/Elements/src/BIM/Door/Door.cs b/Elements/src/BIM/Door/Door.cs deleted file mode 100644 index f16afb685..000000000 --- a/Elements/src/BIM/Door/Door.cs +++ /dev/null @@ -1,493 +0,0 @@ -using Elements.Geometry; -using System; -using System.Collections.Generic; -using System.Text; -using Newtonsoft.Json; -using Elements.Geometry.Solids; -using System.Linq; - -namespace Elements -{ - /// Definition of a door - public class Door : GeometricElement - { - /// The material to be used on the door frame - public Material FrameMaterial { get; set; } = new Material(Colors.Gray, 0.5, 0.25, false, null, false, false, null, false, null, 0, false, default, "Silver Frame"); - /// The opening type of the door that should be placed - [JsonProperty("Door Opening Type")] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - public DoorOpeningType OpeningType { get; private set; } - /// The opening side of the door that should be placed - [JsonProperty("Door Opening Side")] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - public DoorOpeningSide OpeningSide { get; private set; } - /// Width of a door without a frame. - [JsonProperty("Door Width")] - public double DoorWidth { get; set; } - /// Height of a door without a frame. - [JsonProperty("Door Height")] - public double DoorHeight { get; set; } - /// Type of door (Glass or Solid). - [JsonProperty("Door Type")] - public string DoorType { get; set; } - /// Default door thickness. - public static double DEFAULT_DOOR_THICKNESS = Units.InchesToMeters(2.0); - /// Door thickness. - public double DoorThickness { get; set; } = DEFAULT_DOOR_THICKNESS; - /// Default thickness of a door frame. - public double FrameDepth { get; set; } = Units.InchesToMeters(4.0); - /// Default width of a door frame. - public double FrameWidth { get; set; } = Units.InchesToMeters(2.0); //2 inches - /// Height of the door handle from the ground - public double HandleHeight { get; set; } = Units.InchesToMeters(42.0); - /// Radius of the fixture against the door - public double HandleBaseRadius { get; set; } = Units.InchesToMeters(1.35); - /// Radius of the handle - public double HandleRadius { get; set; } = Units.InchesToMeters(0.45); - /// Length of the handle - public double HandleLength { get; set; } = Units.InchesToMeters(5.0); - /// Depth of the handle from the face of the door - public double HandleDepth { get; set; } = Units.InchesToMeters(2.0); - /// Original position of the door used for override identity - public Vector3 OriginalPosition { get; set; } - - [JsonIgnore] - private double FullDoorWidthWithoutFrame => GetDoorFullWidthWithoutFrame(); - /// - /// Create a door. - /// - /// The width of a single door. - /// Height of the door without frame. - /// Door thickness. - /// The side where the door opens. - /// The way the door opens. - /// The door's transform. X-direction is aligned with the door, Y-direction is the opening direction. - /// The door's material. - /// The door's representation. - /// Is this an element definition? - /// The door's id. - /// The door's name. - [JsonConstructor] - public Door(double clearWidth, - double clearHeight, - double thickness, - DoorOpeningSide openingSide, - DoorOpeningType openingType, - Transform transform = null, - Material material = null, - Representation representation = null, - bool isElementDefinition = false, - Guid id = default, - string name = "Door" - ) : base( - transform: transform, - representation: representation, - isElementDefinition: isElementDefinition, - id: id, - name: name - ) - { - OpeningSide = openingSide; - OpeningType = openingType; - DoorHeight = clearHeight; - DoorWidth = clearWidth; - DoorThickness = thickness; - Material = material ?? BuiltInMaterials.Default; - } - - /// - /// Create a door at the certain point of a line. - /// - /// The line where the door is placed. - /// Relative position on the line where door is placed. Should be in [0; 1]. - /// The width of a single door. - /// Height of the door without frame. - /// Door thickness. - /// The side where the door opens. - /// The way the door opens. - /// The door's material. - /// The door's representation. - /// Is this an element definition? - /// The door's id. - /// The door's name. - public Door(Line line, - double tPos, - double clearWidth, - double clearHeight, - double thickness, - DoorOpeningSide openingSide, - DoorOpeningType openingType, - Material material = null, - Representation representation = null, - bool isElementDefinition = false, - Guid id = default, - string name = "Door" - ) : base( - representation: representation, - isElementDefinition: isElementDefinition, - id: id, - name: name - ) - { - OpeningType = openingType; - OpeningSide = openingSide; - DoorWidth = clearWidth; - DoorHeight = clearHeight; - DoorThickness = thickness; - Material = material ?? BuiltInMaterials.Default; - Transform = GetDoorTransform(line.PointAtNormalized(tPos), line); - } - - /// - /// Create an opening for the door. - /// - /// The door's opening depth front. - /// The door's opening depth back. - /// Is the opening flipped? - /// An opening where the door can be inserted. - public Opening CreateDoorOpening(double depthFront, double depthBack, bool flip) - { - var openingWidth = FullDoorWidthWithoutFrame + 2 * FrameWidth; - var openingHeight = DoorHeight + FrameWidth; - - var openingDir = flip ? Vector3.YAxis.Negate() : Vector3.YAxis; - var widthDir = flip ? Vector3.XAxis.Negate() : Vector3.XAxis; - var openingTransform = new Transform(0.5 * openingHeight * Vector3.ZAxis, widthDir, openingDir); - - var openingPolygon = Polygon.Rectangle(openingWidth, openingHeight).TransformedPolygon(openingTransform); - - var opening = new Opening(openingPolygon, openingDir, depthFront, depthBack, Transform); - return opening; - } - - private Transform GetDoorTransform(Vector3 currentPosition, Line wallLine) - { - var adjustedPosition = GetClosestValidDoorPos(wallLine, currentPosition); - var xDoorAxis = wallLine.Direction(); - return new Transform(adjustedPosition, xDoorAxis, Vector3.ZAxis); - } - - /// - /// Update the representations. - /// - public override void UpdateRepresentations() - { - if (RepresentationInstances.Count == 0) - { - DoorRepresentationStorage.SetDoorRepresentation(this); - } - } - - /// - /// Get Hash for representation storage dictionary - /// - public string GetRepresentationHash() - { - return $"{this.GetType().Name}-{this.DoorWidth}-{this.DoorHeight}-{this.DoorThickness}-{this.FrameDepth}-{this.FrameWidth}{this.FrameMaterial.Name}-{this.OpeningType}-{this.OpeningSide}-{this.Material.Name}"; - } - - public List GetInstances() - { - var representationInstances = new List() - { - this.CreateDoorSolidRepresentation(), - this.CreateDoorFrameRepresentation(), - this.CreateDoorHandleRepresentation() - }; - - representationInstances.AddRange(this.CreateDoorCurveRepresentation()); - - return representationInstances.Where(instance => instance != null).ToList(); - } - - private Vector3 GetClosestValidDoorPos(Line wallLine, Vector3 currentPosition) - { - var fullWidth = FullDoorWidthWithoutFrame + FrameWidth * 2; - double wallWidth = wallLine.Length(); - Vector3 p1 = wallLine.PointAt(0.5 * fullWidth); - Vector3 p2 = wallLine.PointAt(wallWidth - 0.5 * fullWidth); - var reducedWallLine = new Line(p1, p2); - return currentPosition.ClosestPointOn(reducedWallLine); - } - - private double GetDoorFullWidthWithoutFrame() - { - switch (this.OpeningSide) - { - case DoorOpeningSide.LeftHand: - case DoorOpeningSide.RightHand: - return this.DoorWidth; - case DoorOpeningSide.DoubleDoor: - return this.DoorWidth * 2; - } - return 0; - } - - private List CreateDoorCurveRepresentation() - { - var repInstances = CollectPointsForSchematicVisualization(); - - return repInstances; - } - - private RepresentationInstance CreateDoorFrameRepresentation() - { - if (FrameDepth == 0 || FrameWidth == 0) - { - return null; - } - - Vector3 left = Vector3.XAxis * (FullDoorWidthWithoutFrame / 2); - Vector3 right = Vector3.XAxis.Negate() * (FullDoorWidthWithoutFrame / 2); - - var frameLeft = left + Vector3.XAxis * this.FrameWidth; - var frameRight = right - Vector3.XAxis * this.FrameWidth; - var frameOffset = Vector3.YAxis * this.FrameDepth / 2; - var doorFramePolygon = new Polygon(new List() { - left + Vector3.ZAxis * this.DoorHeight - frameOffset, - left - frameOffset, - frameLeft - frameOffset, - frameLeft + Vector3.ZAxis * (this.DoorHeight + this.FrameWidth) - frameOffset, - frameRight + Vector3.ZAxis * (this.DoorHeight + this.FrameWidth) - frameOffset, - frameRight - frameOffset, - right - frameOffset, - right + Vector3.ZAxis * this.DoorHeight - frameOffset }); - var doorFrameExtrude = new Extrude(new Profile(doorFramePolygon), this.FrameDepth, Vector3.YAxis); - - var solidRep = new SolidRepresentation(doorFrameExtrude); - solidRep.SetSnappingPoints(new List()); - var repInstance = new RepresentationInstance(solidRep, FrameMaterial, true); - return repInstance; - } - - private RepresentationInstance CreateDoorSolidRepresentation() - { - Vector3 left = Vector3.XAxis * (FullDoorWidthWithoutFrame / 2); - Vector3 right = Vector3.XAxis.Negate() * (FullDoorWidthWithoutFrame / 2); - - var doorPolygon = new Polygon(new List() { - left + Vector3.YAxis * this.DoorThickness/2, - left - Vector3.YAxis * this.DoorThickness/2, - right - Vector3.YAxis * this.DoorThickness/2, - right + Vector3.YAxis * this.DoorThickness/2}); - - var doorPolygons = new List(); - - if (this.OpeningSide == DoorOpeningSide.DoubleDoor) - { - doorPolygons = doorPolygon.Split(new Polyline(new Vector3(0, this.DoorThickness / 2, 0), new Vector3(0, -this.DoorThickness / 2, 0))); - } - else - { - doorPolygons.Add(doorPolygon); - } - - var doorExtrusions = new List(); - - foreach (var polygon in doorPolygons) - { - var doorExtrude = new Extrude(new Profile(polygon.Offset(-0.005)[0]), this.DoorHeight, Vector3.ZAxis); - doorExtrusions.Add(doorExtrude); - } - - var solidRep = new SolidRepresentation(doorExtrusions); - solidRep.SetSnappingPoints(new List(new SnappingPoints[] { new SnappingPoints(new[] { left, Vector3.Origin, right }, SnappingEdgeMode.LineStrip) })); - var repInstance = new RepresentationInstance(solidRep, this.Material, true); - return repInstance; - } - - private List CollectPointsForSchematicVisualization() - { - var representationInstances = new List(); - - if (this.OpeningSide == DoorOpeningSide.Undefined || this.OpeningType == DoorOpeningType.Undefined) - { - return representationInstances; - } - - if (this.OpeningSide != DoorOpeningSide.LeftHand) - { - var points = CollectSchematicVisualizationLines(this, false, false, 90); - points.Add(points[0]); - var curve = new IndexedPolycurve(points); - var curveRep = new CurveRepresentation(curve, false); - curveRep.SetSnappingPoints(new List()); - var repInstance = new RepresentationInstance(curveRep, BuiltInMaterials.Black); - representationInstances.Add(repInstance); - } - - if (this.OpeningSide != DoorOpeningSide.RightHand) - { - var points = CollectSchematicVisualizationLines(this, true, false, 90); - points.Add(points[0]); - var curve = new IndexedPolycurve(points); - var curveRep = new CurveRepresentation(curve, false); - curveRep.SetSnappingPoints(new List()); - var repInstance = new RepresentationInstance(curveRep, BuiltInMaterials.Black); - representationInstances.Add(repInstance); - } - - if (this.OpeningType == DoorOpeningType.DoubleSwing) - { - - if (this.OpeningSide != DoorOpeningSide.LeftHand) - { - var points = CollectSchematicVisualizationLines(this, false, true, 90); - points.Add(points[0]); - var curve = new IndexedPolycurve(points); - var curveRep = new CurveRepresentation(curve, false); - curveRep.SetSnappingPoints(new List()); - var repInstance = new RepresentationInstance(curveRep, BuiltInMaterials.Black); - representationInstances.Add(repInstance); - } - - if (this.OpeningSide != DoorOpeningSide.RightHand) - { - var points = CollectSchematicVisualizationLines(this, true, true, 90); - points.Add(points[0]); - var curve = new IndexedPolycurve(points); - var curveRep = new CurveRepresentation(curve, false); - curveRep.SetSnappingPoints(new List()); - var repInstance = new RepresentationInstance(curveRep, BuiltInMaterials.Black); - representationInstances.Add(repInstance); - } - } - - return representationInstances; - } - - private List CollectSchematicVisualizationLines(Door door, bool leftSide, bool inside, double angle) - { - // Depending on which side door in there are different offsets. - var doorOffset = leftSide ? FullDoorWidthWithoutFrame / 2 : -FullDoorWidthWithoutFrame / 2; - var horizontalOffset = leftSide ? door.DoorThickness : -door.DoorThickness; - var verticalOffset = inside ? door.DoorThickness : -door.DoorThickness; - var widthOffset = inside ? door.DoorWidth : -door.DoorWidth; - - // Draw open door silhouette rectangle. - Vector3 corner = Vector3.XAxis * doorOffset; - var c0 = corner + Vector3.YAxis * verticalOffset; - var c1 = c0 + Vector3.YAxis * widthOffset; - var c2 = c1 - Vector3.XAxis * horizontalOffset; - var c3 = c0 - Vector3.XAxis * horizontalOffset; - - // Rotate silhouette is it's need to be drawn as partially open. - if (!angle.ApproximatelyEquals(90)) - { - double rotation = 90 - angle; - if (!leftSide) - { - rotation = -rotation; - } - - if (!inside) - { - rotation = -rotation; - } - - Transform t = new Transform(); - t.RotateAboutPoint(c0, Vector3.ZAxis, rotation); - c1 = t.OfPoint(c1); - c2 = t.OfPoint(c2); - c3 = t.OfPoint(c3); - } - List points = new List() { c0, c1, c1, c2, c2, c3, c3, c0 }; - - // Calculated correct arc angles based on door orientation. - double adjustedAngle = inside ? angle : -angle; - double anchorAngle = leftSide ? 180 : 0; - double endAngle = leftSide ? 180 - adjustedAngle : adjustedAngle; - if (endAngle < 0) - { - endAngle = 360 + endAngle; - anchorAngle = 360; - } - - // If arc is constructed from bigger angle to smaller is will have incorrect domain - // with max being smaller than min and negative length. - // ToPolyline will return 0 points for it. - // Until it's fixed angles should be aligned manually. - bool flipEnds = endAngle < anchorAngle; - if (flipEnds) - { - (anchorAngle, endAngle) = (endAngle, anchorAngle); - } - - // Draw the arc from closed door to opened door. - Arc arc = new Arc(c0, door.DoorWidth, anchorAngle, endAngle); - var tessalatedArc = arc.ToPolyline((int)(Math.Abs(angle) / 2)); - for (int i = 0; i < tessalatedArc.Vertices.Count - 1; i++) - { - points.Add(tessalatedArc.Vertices[i]); - points.Add(tessalatedArc.Vertices[i + 1]); - } - - return points; - } - - private RepresentationInstance CreateDoorHandleRepresentation() - { - var solidOperationsList = new List(); - - if (OpeningSide == DoorOpeningSide.DoubleDoor) - { - var handlePair1 = CreateHandlePair(DoorWidth / 2 + Units.InchesToMeters(3.0), false); - solidOperationsList.AddRange(handlePair1); - - var handlePair2 = CreateHandlePair(DoorWidth / 2 + Units.InchesToMeters(3.0), true); - solidOperationsList.AddRange(handlePair2); - } - else if (OpeningSide != DoorOpeningSide.Undefined) - { - var xPos = OpeningSide == DoorOpeningSide.LeftHand ? Units.InchesToMeters(3.0) : Units.InchesToMeters(3.0); - var handle = CreateHandlePair(xPos, OpeningSide == DoorOpeningSide.LeftHand); - solidOperationsList.AddRange(handle); - } - - var solidRep = new SolidRepresentation(solidOperationsList); - solidRep.SetSnappingPoints(new List()); - var repInst = new RepresentationInstance(solidRep, FrameMaterial); - return repInst; - } - - private List CreateHandlePair(double handleOffset, bool isCodirectionalToX) - { - var handleDir = isCodirectionalToX ? Vector3.XAxis : Vector3.XAxis.Negate(); - - var xOffset = (-DoorWidth / 2 + handleOffset) * handleDir; - var yOffset = DoorThickness / 2 * Vector3.YAxis; - var zOffset = HandleHeight * Vector3.ZAxis; - - var solidOperationsList = new List(); - - var handleOrigin1 = xOffset + yOffset + zOffset; - var handle1Ops = CreateHandle(handleOrigin1, handleDir, Vector3.YAxis); - solidOperationsList.AddRange(handle1Ops); - - var handleOrigin2 = xOffset - yOffset + zOffset; - var handle2Ops = CreateHandle(handleOrigin2, handleDir, Vector3.YAxis.Negate()); - solidOperationsList.AddRange(handle2Ops); - - return solidOperationsList; - } - - private List CreateHandle(Vector3 origin, Vector3 handleDir, Vector3 yDir) - { - var circleTransform = new Transform(origin, handleDir, yDir); - var circle = new Circle(circleTransform, HandleBaseRadius).ToPolygon(); - var circleOperation = new Extrude(circle, 0.1 * HandleDepth, yDir.Negate()); - - var cyl1Transform = new Transform(origin, handleDir, yDir); - var cyl1Circle = new Circle(cyl1Transform, HandleRadius).ToPolygon(); - var cyl1Operation = new Extrude(cyl1Circle, 0.9 * HandleDepth, yDir); - - var cyl2Origin = cyl1Transform.Origin + cyl1Operation.Height * yDir + handleDir.Negate() * HandleRadius; - var cyl2Transform = new Transform(cyl2Origin, handleDir); - var cyl2Circle = new Circle(cyl2Transform, HandleRadius).ToPolygon(); - var cyl2Operation = new Extrude(cyl2Circle, HandleLength, handleDir); - - var handleSolids = new List() { circleOperation, cyl1Operation, cyl2Operation }; - return handleSolids; - } - } -} diff --git a/Elements/src/BIM/Door/DoorOpeningSide.cs b/Elements/src/BIM/Door/DoorOpeningSide.cs deleted file mode 100644 index b33dbe5fe..000000000 --- a/Elements/src/BIM/Door/DoorOpeningSide.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Elements -{ - public enum DoorOpeningSide - { - [System.Runtime.Serialization.EnumMember(Value = @"Undefined")] - Undefined, - [System.Runtime.Serialization.EnumMember(Value = @"Left Hand")] - LeftHand, - [System.Runtime.Serialization.EnumMember(Value = @"Right Hand")] - RightHand, - [System.Runtime.Serialization.EnumMember(Value = @"Double Door")] - DoubleDoor - } -} \ No newline at end of file diff --git a/Elements/src/BIM/Door/DoorOpeningType.cs b/Elements/src/BIM/Door/DoorOpeningType.cs deleted file mode 100644 index 85d893788..000000000 --- a/Elements/src/BIM/Door/DoorOpeningType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Elements -{ - public enum DoorOpeningType - { - [System.Runtime.Serialization.EnumMember(Value = @"Undefined")] - Undefined, - [System.Runtime.Serialization.EnumMember(Value = @"Single Swing")] - SingleSwing, - [System.Runtime.Serialization.EnumMember(Value = @"Double Swing")] - DoubleSwing - } -} \ No newline at end of file diff --git a/Elements/src/BIM/Door/DoorRepresentationStorage.cs b/Elements/src/BIM/Door/DoorRepresentationStorage.cs deleted file mode 100644 index 93f39b015..000000000 --- a/Elements/src/BIM/Door/DoorRepresentationStorage.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using Elements.Geometry.Solids; - -namespace Elements -{ - public static class DoorRepresentationStorage - { - private static readonly Dictionary> _doors = new Dictionary>(); - public static Dictionary> Doors => _doors; - - public static void SetDoorRepresentation(Door door) - { - var hash = door.GetRepresentationHash(); - if (!_doors.ContainsKey(hash)) - { - _doors.Add(hash, door.GetInstances()); - } - door.RepresentationInstances = _doors[hash]; - } - } - -} \ No newline at end of file diff --git a/Elements/src/StandardWall.cs b/Elements/src/StandardWall.cs index 004c3aaf7..af0d1b06b 100644 --- a/Elements/src/StandardWall.cs +++ b/Elements/src/StandardWall.cs @@ -178,16 +178,5 @@ public override void UpdateRepresentations() var profile = new Polygon(new[] { e1.Start, e1.End, e2.End, e2.Start }); this.Representation.SolidOperations.Add(new Extrude(profile, this.Height, Vector3.ZAxis, false)); } - - /// - /// Creates an opening that suits . - /// - /// Properties of will be used to create an opening. - public void AddDoorOpening(Door door) - { - var halfThickness = 0.5 * Thickness; - var opening = door.CreateDoorOpening(halfThickness, halfThickness, false); - Openings.Add(opening); - } } } \ No newline at end of file diff --git a/Elements/test/DoorTest.cs b/Elements/test/DoorTest.cs deleted file mode 100644 index 574171a85..000000000 --- a/Elements/test/DoorTest.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Elements.Geometry; -using Elements.Tests; -using Elements; -using Xunit; - -namespace Elements -{ - public class DoorTest : ModelTest - { - [Fact, Trait("Category", "Examples")] - public void MakeDoorElement() - { - this.Name = nameof(MakeDoorElement); - - var line = new Line(new Vector3(0, 0, 0), new Vector3(10, 10, 0)); - var wall = new StandardWall(line, 0.1, 3.0); - var door = new Door(wall.CenterLine, 0.5, 2.0, 2.0, Door.DEFAULT_DOOR_THICKNESS, DoorOpeningSide.LeftHand, DoorOpeningType.SingleSwing); - wall.AddDoorOpening(door); - - Assert.Single(wall.Openings); - - this.Model.AddElement(wall); - Model.AddElement(door); - } - } -}