Skip to content

Commit

Permalink
Merge pull request #52 from DmytroMuravskyi/dmuravskyi/door-2d-visual…
Browse files Browse the repository at this point in the history
…ization

Doors: add 2D visualization by using TryToGraphicsBuffers override
  • Loading branch information
katehryhorenko authored Jul 21, 2023
2 parents 8236aa4 + 5f91cc6 commit 7924b98
Showing 1 changed file with 100 additions and 5 deletions.
105 changes: 100 additions & 5 deletions LayoutFunctions/Doors/dependencies/Door.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,106 @@ public static bool CanFit(Line wallLine, DoorType type, double width)
return wallLine.Length() - doorWidth > DOOR_FRAME_WIDTH * 2;
}

public override bool TryToGraphicsBuffers(out List<GraphicsBuffers> graphicsBuffers, out string id, out glTFLoader.Schema.MeshPrimitive.ModeEnum? mode)
{
List<Vector3> points = new List<Vector3>();
points.AddRange(CollectSchematicVisualizationLines(true, false, 90));
if( Type == DoorType.Double)
{
points.AddRange(CollectSchematicVisualizationLines(false, false, 90));
}

GraphicsBuffers buffer = new GraphicsBuffers();
Color color = Colors.Black;
for (int i = 0; i < points.Count; i++)
{
buffer.AddVertex(points[i], default, default, color);
buffer.AddIndex((ushort)i);
}

id = $"{this.Id}_door";
// Only one type is allowed, since line are not linked into one loop, LINES is used.
// This mean that each line segment need both endpoints stored, often duplicated.
mode = glTFLoader.Schema.MeshPrimitive.ModeEnum.LINES;
graphicsBuffers = new List<GraphicsBuffers> { buffer };
return true;
}

private List<Vector3> CollectSchematicVisualizationLines(bool leftSide, bool inside, double angle)
{
var doorWidth = Type == DoorType.Double ? ClearWidth / 2 : ClearWidth;

// Depending on which side door in there are different offsets.
var doorOffset = leftSide ? ClearWidth / 2 : -ClearWidth / 2;
var horizontalOffset = leftSide ? DOOR_THICKNESS : -DOOR_THICKNESS;
var verticalOffset = inside ? DOOR_THICKNESS : -DOOR_THICKNESS;
var widthOffset = inside ? doorWidth : -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<Vector3> points = new List<Vector3>() { 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, 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;
}

public override void UpdateRepresentations()
{
var doorWidth = WidthWithoutFrame(ClearWidth, Type);
Vector3 left = Vector3.XAxis * doorWidth / 2;
Vector3 right = Vector3.XAxis.Negate() * doorWidth / 2;
Vector3 left = Vector3.XAxis * ClearWidth / 2;
Vector3 right = Vector3.XAxis.Negate() * ClearWidth / 2;

var doorPolygon = new Polygon(new List<Vector3>() {
left + Vector3.YAxis * DOOR_THICKNESS,
Expand Down Expand Up @@ -74,9 +169,9 @@ private static double WidthWithoutFrame(double internalWidth, DoorType type)
switch (type)
{
case DoorType.Single:
return internalWidth + DOOR_FRAME_WIDTH * 2;
return internalWidth;
case DoorType.Double:
return internalWidth * 2 + DOOR_FRAME_WIDTH * 2;
return internalWidth * 2;
}
return 0;
}
Expand Down

0 comments on commit 7924b98

Please sign in to comment.