forked from mcneel/opennurbs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
opennurbs_convex_poly.h
427 lines (362 loc) · 13.8 KB
/
opennurbs_convex_poly.h
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
/* $NoKeywords: $ */
/*
//
// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
// McNeel & Associates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
*/
#if !defined(ON_CONVEX_POLY_INC_)
#define ON_CONVEX_POLY_INC_
// A Simplex in 3d
class ON_CLASS ON_3dSimplex
{
public:
ON_3dSimplex(); // An empty simplex
explicit ON_3dSimplex(const ON_3dPoint& a); // 0-simplex in 3d
ON_3dSimplex(const ON_3dPoint& a, const ON_3dPoint& b); // 1-simplex
ON_3dSimplex(const ON_3dPoint& a, const ON_3dPoint& b, const ON_3dPoint& c); // 2-simplex
ON_3dSimplex(const ON_3dPoint& a, const ON_3dPoint& b, const ON_3dPoint& c, const ON_3dPoint& d); // 3-simplex
ON_3dSimplex(const ON_3dSimplex& rhs) = default;
ON_3dSimplex& operator=(const ON_3dSimplex& rhs) = default;
~ON_3dSimplex() = default;
int Count() const; // Number of Verticies <=4
bool IsValid(double eps) const; // true if the Verticies are affinely independent
/*
Description:
Evaluate a point in a Simplex from a barycentric coordinate b.
Returns:
The point
b[0] * Vertex[0] + ... + b[Count()-1] * Vertex[Count()-1]
Notes:
If b[0] + ... + b[Count()-1] = 1 and b[i]>=0 for i=0 to Count()-1 then the
returned point is on the simplex
*/
ON_3dPoint Evaluate(const double* b) const;
ON_3dPoint Evaluate(const ON_4dPoint& b) const;
/*
Description:
Find Closest Point to this simplex from a base point P0 or the Origin.
If true is retuned then Evaluate(Bary) is the closest point on the Simplex.
maximum_distance - optional upperbound on closest point. If maximum_distance>=0 is specified and
Dist(P0, Simplex)>maximum_distance then false is returned.
*/
bool GetClosestPoint(const ON_3dPoint& P0, ON_4dPoint& Bary, double maximum_distance = ON_DBL_MAX) const;
bool GetClosestPointToOrigin(ON_4dPoint& Bary) const;
/*
Count() Volume() returns
0 0.0
1 0.0
2 length >=0
3 area >=0
4 volume >=0
*/
double Volume() const;
double SignedVolume() const; // returns ON_UNSET_VALUE if Count()<4 else the signed volume
/*
FaceNormal(noti) is the oriented face normal obtained by omitting vertex noti.
FaceNormal returns ON_UNSET_VALUE if Count()<3 or Count()==4 noti not 0,1,2 or 3.
FaceUnitNormal returns ON_UNSET_VALUE if Count()<3 or Count()==4 noti not 0,1,2 or 3 or if FaceNormal(noti)=Zero_Vector
*/
ON_3dVector FaceNormal(int noti = 0) const;
ON_3dVector FaceUnitNormal(int noti = 0) const;
/*
Edge vector from Vertex(e0) to Vertex(e1)
*/
ON_3dVector Edge(int e0, int e1)const;
/* If 0<=i<Count() modify this simplex by removing Vertex[i], specifically,
Vertex[k] is fixed for k<i , and
Vertex[k] <- Vertex[k+1] for i<= k= Count()-2
*/
bool RemoveVertex(int i);
/* append new vertex at end*/
bool AddVertex(const ON_3dPoint&);
/* Modify a vertex. i<Count() */
bool SetVertex(int i, ON_3dPoint P);
// Returns a Vertex or a reference to one when 0<=i<Count()
ON_3dPoint& operator[](int);
const ON_3dPoint& operator[](int i) const;
ON_3dPoint Vertex(int i) const;
ON_3dPoint& Vertex(int i);
/* Maximum absolute value of vertex coordinates*/
double MaximumCoordinate() const;
/*
Description:
Get Simplex's 3d axis aligned bounding box.
Returns:
3d bounding box.
*/
ON_BoundingBox BoundingBox() const;
/*
Description:
Get simplexes 3d axis aligned bounding box or the
union of the input box with the object's bounding box.
Parameters:
bbox - [in/out] 3d axis aligned bounding box
bGrowBox - [in] (default=false)
If true, then the union of the input bbox and the
object's bounding box is returned in bbox.
If false, the object's bounding box is returned in bbox.
Returns:
true if object has bounding box and calculation was successful.
*/
bool GetBoundingBox(
ON_BoundingBox& bbox,
int bGrowBox = false
) const;
/*
Description:
Get tight bounding box with respect to a given frame
Parameters:
tight_bbox - [in/out] tight bounding box
bGrowBox -[in] (default=false)
If true and the input tight_bbox is valid, then returned
tight_bbox is the union of the input tight_bbox and the
line's tight bounding box.
xform -[in] (default=nullptr)
If not nullptr, the tight bounding box of the transformed
triangle is calculated. The triangle is not modified.
Returns:
True if a valid tight_bbox is returned.
*/
bool GetTightBoundingBox(
ON_BoundingBox& tight_bbox,
bool bGrowBox = false,
const ON_Xform* xform = nullptr
) const;
bool Transform(
const ON_Xform& xform
);
// rotate line about a point and axis
bool Rotate(
double sin_angle,
double cos_angle,
const ON_3dVector& axis_of_rotation,
const ON_3dPoint& center_of_rotation
);
bool Rotate(
double angle_in_radians,
const ON_3dVector& axis_of_rotation,
const ON_3dPoint& center_of_rotation
);
bool Translate(
const ON_3dVector& delta
);
private:
int m_n; // Number of points stored in m_V. 0<= m_n <= 4
ON_3dVector m_V[4];
bool Closest3plex(ON_4dPoint& Bary) const;
bool Closest2plex(ON_4dPoint& Bary) const;
bool Closest1plex(ON_4dPoint& Bary) const;
static bool RoundBarycentricCoordinate(ON_4dPoint& Bary);
};
/*
This is a base class for a convex polytope in 3d space, i.e. the convex hull of a
finite set of points called verticies.
This is the base type in the implementation of the GJK algorithm
ClosestPoint(ON_ConvexPoly& A, ON_ConvexPoly& B, ...)
*/
class ON_CLASS ON_ConvexPoly
{
public:
/*
Returns: Number of verticies >=0
*/
virtual int Count() const = 0;
/*
Returns: Vertex[i] for i=0,...,Count()-1
*/
virtual ON_3dVector Vertex(int i) const = 0;
/*
Description:
Let K be this ON_ConvexPoly then for a non-zero vector W the support Support(W) are point in K defined by
arg max x * W
x \in K
This method returns one of these points in Support(W).
i0 is an optional initial index seed value. It may provide a performance enhancement toward finding
a minimizer.
*/
ON_3dPoint Support(ON_3dVector W, int i0 =0) const
{
return Vertex(SupportIndex(W, i0));
}
/*
Description:
For any vector W there is a vetex that is Support(W)
SupportIndex( W, i0) returns a vertex index for a vertex that is the support.
Veretx( K.SupportIndex( W )) = K.Support(W );
*/
virtual int SupportIndex(ON_3dVector W, int i0=0) const = 0;
/*
Description:
Points in a Convex Polytope are parameterized , not necessaily uniquely,
by an ON_4dex of vertex indicies and a 4d barycentric point B
Evaluate(Ind, B ) = Sum_{i=0,..,3} Vertex(Ind[i])*B[i], where the sum is taken over i such that Ind[i]>=0
If B is a barycentric coordinte
B[i]>=0 and B[0] + B[1] + B[2] + B[3] = 1.0
then Evaluate( Ind, B) is a point in the convex polytope
*/
ON_3dPoint Evaluate(ON_4dex dex, ON_4dPoint B)const
{
ON_3dVector v(0, 0, 0);
if (dex.i >= 0)
v = B[0] * Vertex(dex.i);
if (dex.j >= 0)
v += B[1] * Vertex(dex.j);
if (dex.k >= 0)
v += B[2] * Vertex(dex.k);
if (dex.l >= 0)
v += B[3] * Vertex(dex.l);
return v;
};
/*
Description:
Computes the closest point on this convex polytope from a point P0.
Parameters:
P0 - [in] Base Point for closest point
dex -[out]
bary - [out] Evaluate(dex,bary) is the closest point on this polyhedran
maximum_distance - [in ] optional upper bound on distance
Returns:
Returns true if a closest point is found and it is within optional maximum_distance bound;
Details:
Setting maximum_distance can speedup the calculation in cases where dist(P0, *this)>maximum_distance.
*/
bool GetClosestPoint( ON_3dPoint P0,
ON_4dex& dex, ON_4dPoint& bary,
double maximum_distance = ON_DBL_MAX) const;
// Expert version of GetClosestPoint.
// dex is used at input to seed search algorithm.
// the points of *this singled out by dex must define a nondegenerate simplex
bool GetClosestPointSeeded(ON_3dPoint P0,
ON_4dex& dex, ON_4dPoint& Bary,
double maximum_distance = ON_DBL_MAX) const;
/*
Description:
Computes a pair of points on *this and BHull that achieve the minimum distance between
the two convex polytopes.
Parameters:
BHull - [in] the other convex polytope
adex, bdex -[out] Evaluate(adex,bary) is the closest point on this polyhedron
bary - [out] BHull.Evaluate(bdex,bary) is the closest point on BHull.
maximum_distance - [in ] optional upper bound on distance
Returns:
Returns true if a closest points are found and they are within optional maximum_distance bound;
Details:
Setting maximum_distance can speedup the calculation in cases where dist(*this, BHull)>maximum_distance.
*/
bool GetClosestPoint(const ON_ConvexPoly& BHull,
ON_4dex& Adex, ON_4dex& Bdex, ON_4dPoint& bary,
double maximum_distance = ON_DBL_MAX) const;
// Expert version of GetClosestPoint.
// Adex and Bdex are used at input to seed search algorithm.
// the points of this-Bhull singled out by Adex and Bdex must define a nondegenerate simplex
bool GetClosestPointSeeded(const ON_ConvexPoly& BHull,
ON_4dex& Adex, ON_4dex& Bdex, ON_4dPoint& bary,
double maximum_distance = ON_DBL_MAX) const;
/*
Description:
This is a bound on the collection of verticies.
Vertex(i).MaximumCoordinate()<= MaximumCoordinate() for all i
*/
virtual double MaximumCoordinate() const = 0;
/*
Description:
A point represented by a ON_4dex D and a barycentric coordinate B
can be put in a standard form so that non-negative elements of D are unique and
corresponding coordinates are positive. Furthemore, the non-negative
indicies are all listed before the unset ( neagative ) values
*/
static bool Standardize(ON_4dex& D, ON_4dPoint& B);
/*
Returns:
true if d[i]<n for i=0..3 a valid ON_4dex for a point in a ON_ConvexPolyBase with Count()=n
*/
static bool IsValid4DexN(const ON_4dex& D, int n)
{
for (int i = 0; i < 4; i++) {
if (D[i] > n) return false;
}
return true;
}
bool IsValid4Dex(const ON_4dex& D) const { return IsValid4DexN(D, Count()); };
virtual ~ON_ConvexPoly() {};
};
// 3d convex hull defined by an explicit collection of points called verticies.
// Note: verticies need not be extreme points
// WARNING: Points are referenced not stored for optimal performance in'
// some applications.
// The list of points must remain alive and in there initial location
// For the duration of this object.
class ON_CLASS ON_ConvexHullRef : public ON_ConvexPoly
{
public:
ON_ConvexHullRef() { m_n = 0; m_is_rat = false; m_stride = 3; };
ON_ConvexHullRef(const ON_3dVector* V0, int count); // a 3d point array
ON_ConvexHullRef(const ON_3dPoint* V0, int count); // a 3d point array
ON_ConvexHullRef(const ON_4dPoint* V0, int count); // a array of homogeneous points
ON_ConvexHullRef(const double* v0, bool is_rat, int n); // v0 is an array of 3dpoints or homo 4d points
ON_ConvexHullRef(const double* v0, bool is_rat, int n, int stride); // v0 is an array of 3dpoints or homo 4d points
void Initialize(const ON_3dVector* V0, int count);
void Initialize(const ON_4dPoint* V0, int count);
void Initialize(const double* V0, ON::point_style style, int count); // style must be either not_rational or homogeneous_rational = 2,
int Count() const override { return m_n; }
ON_3dVector Vertex(int j) const override;
// Support map
virtual int SupportIndex(ON_3dVector W, int i0) const override;
virtual double MaximumCoordinate() const override;
virtual ~ON_ConvexHullRef() override {};
private:
int m_n = 0;
bool m_is_rat= false;
const double* m_v = nullptr;
int m_stride=3;
};
// 3d convex hull defined by an explicit collection of points called verticies.
// Note: verticies need not be extreme points
class ON_CLASS ON_ConvexHullPoint2 : public ON_ConvexPoly
{
public:
ON_ConvexHullPoint2() = default;
ON_ConvexHullPoint2(int init_capacity) : m_Vert(init_capacity) {};
virtual int Count() const override { return m_Vert.Count(); }
virtual ON_3dVector Vertex(int j) const override { return m_Vert[j]; }
// Support map
virtual int SupportIndex(ON_3dVector W, int i0) const override {
return Ref.SupportIndex(W, i0);
};
virtual double MaximumCoordinate() const override;
virtual ~ON_ConvexHullPoint2() override {};
int AppendVertex(const ON_3dPoint& P); // return index of new vertex. must set Adjacent Indicies.
void Empty();
bool SetCapacity(int vcnt) {
m_Vert.SetCapacity(vcnt);
return true;
};
private:
ON_ConvexHullRef Ref;
ON_SimpleArray<ON_3dVector> m_Vert;
};
/*
Compute Convex hull of 2d points
Parameters:
Pnt - array of points, this is array of working data. The points are sorted in place as part of the algorithm
HUll - the sequence Hull[0], HUll[1]... ,*Hull.Last() == Hull[0] defines the convex hull with a positive orientation retuns 2.
PntInd - otional array to be filled in so that Hull[i] = Pnt[ PntInd[i]] where Pnt is the original input point
Returns
dimension of the convex hull
2 - Hull is 2 dimensional
1 - Hull is a line segments
0 - hull is a point
<0 error
*/
ON_DECL
int ON_ConvexHull2d(const ON_SimpleArray<ON_2dPoint>& Pnt, ON_SimpleArray<ON_2dPoint>& Hull, ON_SimpleArray< int>* PntInd = nullptr);
#endif