Skip to content

Commit

Permalink
Doors: add 2D visualization by using TryToGraphicsBuffers override
Browse files Browse the repository at this point in the history
  • Loading branch information
DmytroMuravskyi committed Jul 21, 2023
1 parent 68d79d7 commit d1631b6
Showing 1 changed file with 96 additions and 0 deletions.
96 changes: 96 additions & 0 deletions LayoutFunctions/Doors/dependencies/Door.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,102 @@ 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(DoorSchema(true, false, 90));
if( Type == DoorType.Double)
{
points.AddRange(DoorSchema(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> DoorSchema(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))
{
Transform t = new Transform();
double rotation = 90 - angle;
if (!leftSide)
{
rotation = -rotation;
}

if (!inside)
{
rotation = -rotation;
}

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()
{
Vector3 left = Vector3.XAxis * ClearWidth / 2;
Expand Down

0 comments on commit d1631b6

Please sign in to comment.