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

Added optional snapping points generation; #1049

Merged
merged 8 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
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
10 changes: 10 additions & 0 deletions Elements/src/CoreModels/ElementRepresentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@ internal virtual List<NodeExtension> GetNodeExtensions(GeometricElement element)
{
return new List<NodeExtension>();
}

/// <summary>
///Creates the set of snapping points
/// </summary>
/// <param name="element">The element with this representation.</param>
/// <returns></returns>
public virtual List<SnappingPoints> CreateSnappingPoints(GeometricElement element)
{
return new List<SnappingPoints>();
}
}
2 changes: 1 addition & 1 deletion Elements/src/CoreModels/RepresentationInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public RepresentationInstance(ElementRepresentation representation, Material mat
public List<string> RepresentationTypes { get; set; } = new List<string>();

/// <summary>
/// Indicates if this element representation instance is displayed by default.
/// Indicates if this element representation instance is displayed by default.
/// Element can have several default representations.
/// </summary>
public bool IsDefault { get; set; } = true;
Expand Down
32 changes: 32 additions & 0 deletions Elements/src/Geometry/Solids/Extrude.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Elements.Validators;
using Newtonsoft.Json;

Expand Down Expand Up @@ -108,6 +109,37 @@ public Extrude(Profile profile, double height, Vector3 direction, bool isVoid =
UpdateGeometry();
}

internal override List<SnappingPoints> CreateSnappingPoints(GeometricElement element)
{
var result = new List<SnappingPoints>();
var localTransform = new Transform(Direction * Height);
var bottomVertices = new List<Vector3>();
// add perimeter bottom points
result.Add(new SnappingPoints(Profile.Perimeter.Vertices, SnappingEdgeMode.LineLoop));
bottomVertices.AddRange(Profile.Perimeter.Vertices);
// add perimeter top points
result.Add(new SnappingPoints(Profile.Perimeter.TransformedPolygon(localTransform).Vertices, SnappingEdgeMode.LineLoop));

// add each void
foreach (var item in Profile.Voids)
{
result.Add(new SnappingPoints(item.Vertices, SnappingEdgeMode.LineLoop));
bottomVertices.AddRange(item.Vertices);
result.Add(new SnappingPoints(item.TransformedPolygon(localTransform).Vertices, SnappingEdgeMode.LineLoop));
}

// connect top and bottom points
var edges = new List<Vector3>();
foreach (var item in bottomVertices)
{
edges.Add(item);
edges.Add(localTransform.OfPoint(item));
}
result.Add(new SnappingPoints(edges, SnappingEdgeMode.Lines));

return result;
}

private void UpdateGeometry()
{
this._solid = Kernel.Instance.CreateExtrude(this._profile, this._height, this._direction, this._reverseWinding);
Expand Down
13 changes: 13 additions & 0 deletions Elements/src/Geometry/Solids/Lamina.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ public Lamina(Profile profile, bool isVoid = false) : this(profile.Perimeter, pr

}

internal override List<SnappingPoints> CreateSnappingPoints(GeometricElement element)
{
var result = new List<SnappingPoints>();
result.Add(new SnappingPoints(Perimeter.Vertices, SnappingEdgeMode.LineLoop));

foreach (var item in Voids)
{
result.Add(new SnappingPoints(item.Vertices, SnappingEdgeMode.LineLoop));
}

return result;
}

private void UpdateGeometry()
{
this._solid = Kernel.Instance.CreateLamina(this._perimeter, this._voids);
Expand Down
6 changes: 6 additions & 0 deletions Elements/src/Geometry/Solids/SolidOperation.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace Elements.Geometry.Solids
Expand Down Expand Up @@ -53,5 +54,10 @@ protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.Cal
if (handler != null)
handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}

internal virtual List<SnappingPoints> CreateSnappingPoints(GeometricElement element)
{
return new List<SnappingPoints>();
}
}
}
6 changes: 6 additions & 0 deletions Elements/src/Geometry/Solids/Sweep.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace Elements.Geometry.Solids
Expand Down Expand Up @@ -109,6 +110,11 @@ public double ProfileRotation
}
}

internal override List<SnappingPoints> CreateSnappingPoints(GeometricElement element)
{
return base.CreateSnappingPoints(element);
}

private void UpdateGeometry()
{
this._solid = Kernel.Instance.CreateSweepAlongCurve(this._profile, this._curve, this._startSetback, this._endSetback, this._profileRotation);
Expand Down
9 changes: 9 additions & 0 deletions Elements/src/Representations/CurveRepresentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,14 @@ public override bool TryToGraphicsBuffers(GeometricElement element, out List<Gra
mode = _curve.IsClosedForRendering ? glTFLoader.Schema.MeshPrimitive.ModeEnum.LINE_LOOP : glTFLoader.Schema.MeshPrimitive.ModeEnum.LINE_STRIP;
return true;
}

/// <inheritdoc/>
public override List<SnappingPoints> CreateSnappingPoints(GeometricElement element)
{
var snappingPoints = new List<SnappingPoints>();
var curvePoints = _curve.RenderVertices();
snappingPoints.Add(new SnappingPoints(curvePoints));
return snappingPoints;
}
}
}
13 changes: 13 additions & 0 deletions Elements/src/Representations/SolidRepresentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,5 +191,18 @@ public List<List<Vector3>> CalculateIntersectionPoints(GeometricElement element,

return intersectionPoints;
}

/// <inheritdoc/>
public override List<SnappingPoints> CreateSnappingPoints(GeometricElement element)
{
var snappingPoints = new List<SnappingPoints>();

foreach (var solidOperation in SolidOperations)
{
snappingPoints.AddRange(solidOperation.CreateSnappingPoints(element));
}

return snappingPoints;
}
}
}
36 changes: 36 additions & 0 deletions Elements/src/Serialization/JSON/VectorListToByteArrayConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using Elements.Geometry;
using Newtonsoft.Json;

namespace Elements.Serialization.JSON
{
internal class VectorListToByteArrayConverter : JsonConverter
{
public override bool CanRead => false;

public override bool CanConvert(Type objectType)
{
return objectType == typeof(List<Vector3>);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();

}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var points = value as List<Vector3>;
var valueAsArray = new double[points.Count * 3];
for (int i = 0; i < points.Count; i++)
{
valueAsArray[i * 3] = points[i].X;
valueAsArray[i * 3 + 1] = points[i].Y;
valueAsArray[i * 3 + 2] = points[i].Z;
}
serializer.Serialize(writer, valueAsArray);
}
}
}
18 changes: 18 additions & 0 deletions Elements/src/Serialization/glTF/GltfExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,19 @@ private static void AddExtension(Gltf gltf, glTFLoader.Schema.Node gltfNode, str
gltfNode.Extensions.Add(extensionName, extensionAttributes);
}

/// <summary>
/// Add a custom Mesh extension.
/// </summary>
private static void AddExtension(Gltf gltf, glTFLoader.Schema.Mesh gltfMesh, string extensionName, Dictionary<string, object> extensionAttributes)
{
if (gltfMesh.Extensions == null)
{
gltfMesh.Extensions = new Dictionary<string, object>();
}
AddExtension(gltf, extensionName, extensionAttributes);
gltfMesh.Extensions.Add(extensionName, extensionAttributes);
}

/// <summary>
/// Add a generic custom extension.
/// </summary>
Expand Down Expand Up @@ -1328,6 +1341,11 @@ private static void GetRenderDataForElement(Element e,
var meshIdList = new List<int> { meshId };
representationsMap.Add(combinedId, meshIdList);
addedNodes.AddRange(NodeUtilities.AddNodes(nodes, meshIdList, elementNodeId));
var snappingPoints = representation.Representation.CreateSnappingPoints(element);
if (snappingPoints.Any())
{
AddExtension(gltf, meshes[meshId], "HYPAR_snapping_points", new Dictionary<string, object>() { { "points", snappingPoints } });
}
}
}
else
Expand Down
11 changes: 8 additions & 3 deletions Elements/src/Serialization/glTF/NodeUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ internal static Node AddInstanceAsCopyOfNode(
// Two new nodes are created: a top-level node, which has the
// element's Transform, and one just below that, which handles
// flipping the orientation of the glb to have Z up. That node has
// the node to copy as its only child.
// the node to copy as its only child.
// We use the node to copy exactly as is, with an unmodified
// transform.
// We need the outermost node to be "purely" the element's
Expand All @@ -109,7 +109,7 @@ internal static Node AddInstanceAsCopyOfNode(
var rootTransform = new Transform();
// glb has Y up. transform it to have Z up so we
// can create instances of it in a Z up world. It will get switched
// back to Y up further up in the node hierarchy.
// back to Y up further up in the node hierarchy.
rootTransform.Rotate(new Vector3(1, 0, 0), 90.0);
float[] glbOrientationTransform = TransformToMatrix(rootTransform);
var elementOrientationNode = new glTFLoader.Schema.Node();
Expand Down Expand Up @@ -237,9 +237,14 @@ public static void SetRepresentationInfo(this Node node, RepresentationInstance
var extensionDict = new Dictionary<string, object>
{
{"isDefault", representationInstance.IsDefault},
{"representationType", representationInstance.RepresentationTypes}
{"representationType", representationInstance.RepresentationTypes},
};

if (node.Mesh.HasValue)
{
extensionDict.Add("mesh", node.Mesh.Value);
}

node.Extensions["HYPAR_representation_info"] = extensionDict;
}
}
Expand Down
25 changes: 25 additions & 0 deletions Elements/src/Snapping/SnappingEdgeMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Elements
{
/// <summary>
/// Enumerates the modes for creating snap edges.
/// </summary>
public enum SnappingEdgeMode
{
/// <summary>
/// No edges are created; only individual point snaps.
/// </summary>
Points,
/// <summary>
/// A snap edge is drawn between every pair of points, creating a network of edges.
/// </summary>
Lines,
/// <summary>
/// Snap edges connect each subsequent point and also close the shape by connecting the last to the first point.
/// </summary>
LineLoop,
/// <summary>
/// Snap edges connect each subsequent point, without closing the shape.
/// </summary>
LineStrip
}
}
37 changes: 37 additions & 0 deletions Elements/src/Snapping/SnappingPoints.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using Elements.Geometry;
using Elements.Serialization.JSON;
using Newtonsoft.Json;

namespace Elements
{
/// <summary>
/// Provides information about snapping points.
/// </summary>
public class SnappingPoints
{
/// <summary>
/// Initializes a new instance of SnappingPoints class.
/// </summary>
/// <param name="points">The set of points.</param>
/// <param name="edgeMode">The mode for creating snap edges.</param>
public SnappingPoints(IEnumerable<Vector3> points, SnappingEdgeMode edgeMode = SnappingEdgeMode.LineStrip)
{
Points.AddRange(points);
EdgeMode = edgeMode;
}

/// <summary>
/// Snapping points.
/// </summary>
[JsonProperty("points")]
[JsonConverter(typeof(VectorListToByteArrayConverter))]
public List<Vector3> Points { get; } = new List<Vector3>();

/// <summary>
/// The modes for creating snap edges.
/// </summary>
[JsonProperty("edgeMode")]
public SnappingEdgeMode EdgeMode { get; set; }
}
}
Loading