Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doors: add 2D visualization by using TryToGraphicsBuffers override #52

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading