-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathIsRectangular.cs
More file actions
129 lines (104 loc) · 5.29 KB
/
Copy pathIsRectangular.cs
File metadata and controls
129 lines (104 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2026, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/
using BH.oM.Base.Attributes;
using BH.oM.Geometry;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace BH.Engine.Geometry
{
public static partial class Query
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/
[Description("Determines whether a Polycurve is a rectangular.")]
[Input("polycurve", "The Polycurve to check if it is rectangular.")]
[Output("bool", "True for Polycurves that are rectangular or false for Polycurves that are not rectangular.")]
public static bool IsRectangular(this PolyCurve polycurve)
{
if (polycurve == null)
return false;
if (polycurve.SubParts().Any(x => !x.IIsLinear()))
return false;
List<Point> points = polycurve.DiscontinuityPoints();
if (points.Count != 4)
return false;
if (!points.IsCoplanar())
return false;
List<Vector> vectors = VectorsBetweenPoints(points);
List<double> angles = AnglesBetweenVectors(vectors);
//Check the three angles are pi/2 degrees within tolerance
return (angles.Any(x => Math.Abs(Math.PI / 2 - x) > Tolerance.Angle)) ? false : true;
}
/***************************************************/
[Description("Checks whether a Polyline is a rectangular.")]
[Input("polyline", "The Polyline to check if it is rectangular.")]
[Input("tolerance", "Maximum allowed distance deviation for closure and diagonal equality checks.")]
[Output("isRectangular", "True for the Polylines that are rectangular or false for Polylines that are not rectangular.")]
public static bool IsRectangular(this Polyline polyline, double tolerance = Tolerance.Distance)
{
List<Point> pts = polyline?.ControlPoints;
if (pts == null || pts.Count != 5)
return false;
if (polyline.IsPlanar(tolerance) != true)
return false;
if (polyline.IsClosed(tolerance) != true)
return false;
double diagonal1 = pts[2].Distance(pts[0]);
double diagonal2 = pts[3].Distance(pts[1]);
return Math.Abs(diagonal1 - diagonal2) <= tolerance;
}
/***************************************************/
/**** Private Methods ****/
/***************************************************/
[Description("Computes the vectors between the provided list of points.")]
[Input("points", "The list of points.")]
[Output("vectors", "The vectors computed from the list of points.")]
private static List<Vector> VectorsBetweenPoints(this List<Point> points)
{
List<Vector> vectors = new List<Vector>();
for (int i = 0; i < points.Count; i++)
{
int next = (i + 1) % points.Count;
vectors.Add(points[next] - points[i]);
}
return vectors;
}
/***************************************************/
[Description("Gets the internal angle between sequential vectors.")]
[Input("vectors", "The vectors to find the internal angle between.")]
[Output("angles", "The internal angles between sequential vectors.")]
private static List<double> AnglesBetweenVectors(this List<Vector> vectors)
{
List<double> angles = new List<double>();
for (int i = 0; i < vectors.Count; i++)
{
int next = (i + 1) % vectors.Count;
angles.Add(vectors[i].Angle(vectors[next]));
}
return angles;
}
/***************************************************/
}
}