Files
opennurbs/opennurbs_convex_poly.h
2020-09-11 14:29:29 -07:00

428 lines
14 KiB
C++

/* $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