Skip to content

Commit

Permalink
Merge master into explicit-ref
Browse files Browse the repository at this point in the history
  • Loading branch information
wynged authored Aug 11, 2022
2 parents b3fcb35 + d975c8e commit 6872d96
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 26 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
## 1.2.0

### Added

- Message class along with helper creation methods.

### Changed

- MeshElement constructor signature modified to be compatible with code generation.
- `BBox3.Extend` method is public now
- `AdaptiveGrid.Boundary` can be left null.
- `Obstacle` properties `Points`, `Offset`, `Perimeter` and `Transform` can be modified from outside.

### Fixed

- Fixed a bug where `Polyline.Frames` would return inconsistently-oriented transforms.
- `Obstacle.FromBox` works properly with `AdaptiveGrid` transformation.
- `AdaptiveGrid.SubtractObstacle` worked incorrectly in `AdaptiveGrid.Boundary` had elevation.

## 1.1.0

Expand Down Expand Up @@ -57,7 +64,7 @@
- Fixed a mathematical error in `MercatorProjection.MetersToLatLon`, which was returning longitude values that were skewed.
- `Grid2d.IsTrimmed` would occasionally return `true` for cells that were not actually trimmed.
- `Vector3[].AreCoplanar()` computed its tolerance for deviation incorrectly, this is fixed.
- `Polyline.Intersects(Line line, out List<Vector3> intersections, bool infinite = false, bool includeEnds = false)` fix wrong results when infinite flag is set, fix for overlapping points when include ends is set
- `Polyline.Intersects(Line line, out List<Vector3> intersections, bool infinite = false, bool includeEnds = false)` fix wrong results when infinite flag is set, fix for overlapping points when include ends is set.

## 1.0.1

Expand Down
18 changes: 11 additions & 7 deletions Elements/src/Spatial/AdaptiveGrid/AdaptiveGrid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -951,15 +951,19 @@ private List<Edge> AddEdgesInBetween(Vertex start, Vertex end, IEnumerable<Vecto

private void AddEdgesOnLine(Vector3 start, Vector3 end, IEnumerable<Vector3> candidates)
{
var inside = new Line(new Vector3(start.X, start.Y), new Vector3(end.X, end.Y)).Trim(Boundaries, out var _);
if (!inside.Any())
if (Boundaries != null)
{
return;
}
var boundary2d = new Polygon(Boundaries.Vertices.Select(v => new Vector3(v.X, v.Y)).ToList());
var inside = new Line(new Vector3(start.X, start.Y), new Vector3(end.X, end.Y)).Trim(boundary2d, out var _);
if (!inside.Any())
{
return;
}

var fi = inside.First();
start = new Vector3(fi.Start.X, fi.Start.Y, start.Z);
end = new Vector3(fi.End.X, fi.End.Y, end.Z);
var fi = inside.First();
start = new Vector3(fi.Start.X, fi.Start.Y, start.Z);
end = new Vector3(fi.End.X, fi.End.Y, end.Z);
}

var onLine = candidates.Where(x => Line.PointOnLine(x, start, end));
var ordered = onLine.OrderBy(x => (x - start).Dot(end - start));
Expand Down
11 changes: 5 additions & 6 deletions Elements/src/Spatial/AdaptiveGrid/Obstacle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ public static Obstacle FromWall(StandardWall wall, double offset = 0, bool perim
/// <returns>New obstacle object.</returns>
public static Obstacle FromBBox(BBox3 box, double offset = 0, bool perimeter = false)
{
List<Vector3> points = new List<Vector3>() { box.Min, box.Max };
return new Obstacle(points, offset, perimeter, null);
return new Obstacle(box.Corners(), offset, perimeter, null);
}

/// <summary>
Expand Down Expand Up @@ -132,23 +131,23 @@ public Obstacle(List<Vector3> points, double offset, bool perimeter, Transform t
/// <summary>
/// List of points defining obstacle.
/// </summary>
public List<Vector3> Points { get; private set; }
public List<Vector3> Points { get; set; }

/// <summary>
/// Offset of bounding box created from the list of points.
/// </summary>
public double Offset { get; private set; }
public double Offset { get; set; }

/// <summary>
/// Should edges be created around obstacle.
/// If false - any intersected edges are just discarded.
/// If true - intersected edges are cut to obstacle and perimeter edges are inserted.
/// </summary>
public bool Perimeter { get; private set; }
public bool Perimeter { get; set; }

/// <summary>
/// Transformation of bounding box created from the list of points.
/// </summary>
public Transform Transform { get; private set; }
public Transform Transform { get; set; }
}
}
187 changes: 175 additions & 12 deletions Elements/test/AdaptiveGridTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using Xunit;
using Vertex = Elements.Spatial.AdaptiveGrid.Vertex;
Expand All @@ -16,9 +17,7 @@ public class AdaptiveGridTests : ModelTest
[Fact, Trait("Category", "Examples")]
public void AdaptiveGridPolygonKeyPointsExample()
{
this.Name = "Elements_Spatial_AdaptiveGrid_AdaptiveGrid";
// <example>
var random = new Random();

var adaptiveGrid = new AdaptiveGrid();
var points = new List<Vector3>()
Expand All @@ -32,19 +31,15 @@ public void AdaptiveGridPolygonKeyPointsExample()
adaptiveGrid.AddFromPolygon(Polygon.Rectangle(15, 10).TransformedPolygon(
new Transform(new Vector3(), new Vector3(10, 0, 10))), points);

foreach (var edge in adaptiveGrid.GetEdges())
{
Model.AddElement(new ModelCurve(adaptiveGrid.GetLine(edge), material: random.NextMaterial()));
}
// </example>

WriteToModelWithRandomMaterials(adaptiveGrid, "Elements_Spatial_AdaptiveGrid_AdaptiveGrid");
}

[Fact]
public void AdaptiveGridBboxKeyPointsExample()
{
this.Name = "Elements_Spatial_AdaptiveGrid_AdaptiveGridBboxKeyPoints";
// <example2>
var random = new Random();

var adaptiveGrid = new AdaptiveGrid();
var points = new List<Vector3>()
Expand Down Expand Up @@ -75,11 +70,9 @@ public void AdaptiveGridBboxKeyPointsExample()
};
adaptiveGrid.AddFromPolygon(rectangle.TransformedPolygon(new Transform(new Vector3(0, 0, 2))), points);

foreach (var edge in adaptiveGrid.GetEdges())
{
Model.AddElement(new ModelCurve(adaptiveGrid.GetLine(edge), material: random.NextMaterial()));
}
// </example2>

WriteToModelWithRandomMaterials(adaptiveGrid, "Elements_Spatial_AdaptiveGrid_AdaptiveGridBboxKeyPoints");
}

[Fact]
Expand Down Expand Up @@ -221,6 +214,166 @@ public void AdaptiveGridSubtractMisalignedPolygon()
Assert.Equal(edgesCount - 9, adaptiveGrid.GetEdges().Count);
Assert.Equal(verticiesCount - 2, adaptiveGrid.GetVertices().Count);
}

[Fact]
public void AdaptiveGridSubstructRotatedBox()
{
var polygon = Polygon.Rectangle(new Vector3(0, 0), new Vector3(10, 10));
var transfrom = new Transform().Rotated(Vector3.ZAxis, 45);

var points = new List<Vector3>();
for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
points.Add(new Vector3(i, j));
}
}

var adaptiveGrid = new AdaptiveGrid(transfrom);
adaptiveGrid.AddFromPolygon(polygon, points);

//Obstacle aligned with adaptive grid transformation.
//Forms big (3;1) -> (5;3) -> (3;5) -> (1;3) rectangle.
var bbox = new BBox3(new Vector3(2, 2), new Vector3(4, 4));
var withoutTransfrom = Obstacle.FromBBox(bbox, perimeter: true);
adaptiveGrid.SubtractObstacle(withoutTransfrom);

Assert.False(adaptiveGrid.TryGetVertexIndex(new Vector3(3, 3), out _, adaptiveGrid.Tolerance));
Assert.False(adaptiveGrid.TryGetVertexIndex(new Vector3(3, 2), out _, adaptiveGrid.Tolerance));
Assert.False(adaptiveGrid.TryGetVertexIndex(new Vector3(3, 4), out _, adaptiveGrid.Tolerance));
Assert.False(adaptiveGrid.TryGetVertexIndex(new Vector3(2, 3), out _, adaptiveGrid.Tolerance));
Assert.False(adaptiveGrid.TryGetVertexIndex(new Vector3(4, 3), out _, adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(2, 2), out var id, adaptiveGrid.Tolerance));
var v = adaptiveGrid.GetVertex(id);
Assert.Equal(3, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(1.5, 2.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(2.5, 1.5), adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(4, 2), out id, adaptiveGrid.Tolerance));
v = adaptiveGrid.GetVertex(id);
Assert.Equal(3, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(3.5, 1.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(4.5, 2.5), adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(4, 4), out id, adaptiveGrid.Tolerance));
v = adaptiveGrid.GetVertex(id);
Assert.Equal(3, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(3.5, 4.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(4.5, 3.5), adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(2, 4), out id, adaptiveGrid.Tolerance));
v = adaptiveGrid.GetVertex(id);
Assert.Equal(3, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(1.5, 3.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(2.5, 4.5), adaptiveGrid.Tolerance));

//Obstacle aligned with global transformation.
//Forms small (6;6) -> (8;6) -> (8;8) -> (6;8) rectangle.
bbox = new BBox3(new Vector3(6, 6), new Vector3(8, 8));
var withTransform = Obstacle.FromBBox(bbox, perimeter: true);
withTransform.Transform = new Transform();
adaptiveGrid.SubtractObstacle(withTransform);

Assert.False(adaptiveGrid.TryGetVertexIndex(new Vector3(7, 7), out _, adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(6, 6), out id, adaptiveGrid.Tolerance));
v = adaptiveGrid.GetVertex(id);
Assert.Equal(5, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(6, 7), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(5.5, 6.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(7, 6), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(6.5, 5.5), adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(8, 6), out id, adaptiveGrid.Tolerance));
v = adaptiveGrid.GetVertex(id);
Assert.Equal(5, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(7, 6), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(7.5, 5.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(8, 7), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(8.5, 6.5), adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(8, 8), out id, adaptiveGrid.Tolerance));
v = adaptiveGrid.GetVertex(id);
Assert.Equal(5, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(8, 7), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(8.5, 7.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(7, 8), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(7.5, 8.5), adaptiveGrid.Tolerance));

Assert.True(adaptiveGrid.TryGetVertexIndex(new Vector3(6, 8), out id, adaptiveGrid.Tolerance));
v = adaptiveGrid.GetVertex(id);
Assert.Equal(5, v.Edges.Count);
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(7, 8), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(6.5, 8.5), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(6, 7), adaptiveGrid.Tolerance));
Assert.Contains(v.Edges, e => adaptiveGrid.GetVertex(
e.OtherVertexId(v.Id)).Point.IsAlmostEqualTo(new Vector3(5.5, 7.5), adaptiveGrid.Tolerance));

WriteToModelWithRandomMaterials(adaptiveGrid);
}

[Fact]
public void BrokenSubtractionForMisalignedPolygon()
{
var boundaryVerticies = new List<Vector3>
{
new Vector3(0.241, -40, 7),
new Vector3(0.241, -60, 7),
new Vector3(80, -60.000000000000014, 7),
new Vector3(80, -40.000000000000014, 7)
};

var boundary = new Polygon(boundaryVerticies);

var grid = new AdaptiveGrid()
{
Boundaries = boundary
};

grid.AddFromPolygon(boundary, new[] { Vector3.Origin });

var profile = Polygon.Rectangle(0.2, 0.2);
var column = new Column(
new Vector3(0.5, -56.22727272727274),
10,
new Line(new Vector3(0.5, -56.22727272727274, 10), new Vector3(0.5, -56.22727272727274, 0)),
profile);

var obstacle = Obstacle.FromColumn(column, 0.2, true);
var result = grid.SubtractObstacle(obstacle);

Assert.True(result);
Assert.Equal(8, grid.GetEdges().Count);
Assert.All(grid.GetVertices(), x => Assert.Equal(2, x.Edges.Count));

WriteToModelWithRandomMaterials(grid);
}

[Fact]
public void AdaptiveGridLongSectionDoNowThrow()
{
Expand Down Expand Up @@ -724,5 +877,15 @@ private AdaptiveGrid SampleGrid()
grid.AddVertex(new Vector3(5, 2), new ConnectVertexStrategy(strip[1]), cut: false); //5
return grid;
}

private void WriteToModelWithRandomMaterials(AdaptiveGrid grid, [CallerMemberName] string memberName = "")
{
var random = new Random();
Name = memberName;
foreach (var edge in grid.GetEdges())
{
Model.AddElement(new ModelCurve(grid.GetLine(edge), material: random.NextMaterial()));
}
}
}
}

0 comments on commit 6872d96

Please sign in to comment.