-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathXYZUtils.cs
144 lines (135 loc) · 4.57 KB
/
XYZUtils.cs
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ricaun.Revit.DB.Shape
{
/// <summary>
/// XYZUtils
/// </summary>
public static class XYZUtils
{
private const double Tolerance = 1e-9;
/// <summary>
/// IsAlmostParallelTo
/// </summary>
/// <param name="value"></param>
/// <param name="source"></param>
/// <param name="tolerance"></param>
/// <returns></returns>
public static bool IsAlmostParallelTo(XYZ value, XYZ source, double tolerance = Tolerance)
{
return Math.Abs(value.DotProduct(source)) >= 1.0 - tolerance;
}
/// <summary>
/// ComputeNormal
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p3"></param>
/// <returns></returns>
public static XYZ ComputeNormal(XYZ p1, XYZ p2, XYZ p3)
{
// Calculate the vectors that define the triangle
var v1 = p2 - p1;
var v2 = p3 - p1;
// Compute the cross product of the two vectors to get the normal
var normal = v1.CrossProduct(v2);
// Normalize the normal vector
normal = normal.Normalize();
return normal;
}
internal static XYZ[] CreateCircleLoopVertices(XYZ origin, double radius, int sides = 3)
{
var loopBaseVertices = new XYZ[sides];
for (int i = 0; i < sides; i++)
{
var s = 2 * Math.PI * (double)i / sides;
var x = Math.Sin(s) * radius;
var y = Math.Cos(s) * radius;
var point = new XYZ(x, y, 0) + origin;
loopBaseVertices[i] = point;
}
return loopBaseVertices;
}
internal static bool UpdateLoopWithTriangle(List<XYZ> loop, params XYZ[] values)
{
XYZAlmostEqualComparer comparer = new XYZAlmostEqualComparer();
var valuesCopy = values.ToList();
foreach (var value in values)
{
if (loop.Contains(value, comparer))
{
valuesCopy.Remove(value);
}
}
if (valuesCopy.Count == 1)
{
var value = valuesCopy[0];
var count = loop.Count;
for (int i = 0; i < count + 1; i++)
{
var p1 = loop[(i + 0) % count];
var p2 = loop[(i + 1) % count];
if (values.Contains(p1, comparer))
{
if (values.Contains(p2, comparer))
{
var index = (i + 1) % count;
loop.Insert(index, value);
break;
}
}
}
}
return valuesCopy.Count == 1;
}
/// <summary>
/// XYZAlmostEqualComparer
/// </summary>
public class XYZAlmostEqualComparer : IEqualityComparer<XYZ>, IComparer<XYZ>
{
private const double Tolerance = 1e-9;
private double tolerance;
/// <summary>
/// XYZAlmostEqualComparer
/// </summary>
/// <param name="tolerance"></param>
public XYZAlmostEqualComparer(double tolerance = Tolerance)
{
this.tolerance = tolerance;
}
/// <summary>
/// Compare
/// </summary>
/// <param name="point1"></param>
/// <param name="point2"></param>
/// <returns></returns>
public int Compare(XYZ point1, XYZ point2)
{
if (point1.IsAlmostEqualTo(point2, tolerance))
return 0;
return 1;
}
/// <summary>
/// Equals
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public bool Equals(XYZ x, XYZ y)
{
return x.IsAlmostEqualTo(y, tolerance);
}
/// <summary>
/// GetHashCode
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public int GetHashCode(XYZ obj)
{
return obj.X.GetHashCode() ^ obj.Y.GetHashCode() ^ obj.Z.GetHashCode();
}
}
}
}