Files
create/src/Mod/Path/libarea/kurve/geometry.h
2015-07-23 23:28:33 -03:00

1022 lines
45 KiB
C++

/////////////////////////////////////////////////////////////////////////////////////////
// geometry.lib header
// modified with 2d & 3d vector methods 2006
/////////////////////////////////////////////////////////////////////////////////////////
/*==============================
Copyright (c) 2006 g.j.hawkesford
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
==============================*/
#pragma once
#ifdef WIN32
#pragma warning( disable : 4996 )
#ifndef WINVER
#define WINVER 0x501
#endif
#endif
#include <math.h>
#include <algorithm>
#include <vector>
#include <list>
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
namespace geoff_geometry {
// offset methods
enum OFFSET_METHODS {
NO_ELIMINATION = 0,
BASIC_OFFSET,
ROLLINGBALL_OFFSET // unfinished
};
enum SPAN_IDS {
UNMARKED = 0xe0000000,
ROLL_AROUND,
INTERSECTION,
FULL_CIRCLE_KURVE
};
class Vector2d;
class Vector3d;
class Point;
class Point3d;
class CLine;
class Circle;
class Span;
class Kurve;
class Line;
enum UNITS_TYPE{
MM = 0,
METRES,
INCHES
};
extern int UNITS; // may be enum UNITS_TYPE (MM METRES or INCHES)
extern double TOLERANCE; // CAD Geometry resolution (inexact, eg. from import)
extern double TOLERANCE_SQ; // tolerance squared for faster coding.
extern double TIGHT_TOLERANCE;
extern double UNIT_VECTOR_TOLERANCE;
extern double SMALL_ANGLE; // small angle tangency test eg isConvex
extern double SIN_SMALL_ANGLE;
extern double COS_SMALL_ANGLE;
extern double RESOLUTION; // CNC resolution
void set_Tolerances(int mode);
double mm(double value); // convert to current units from mm
inline bool FEQ(double a, double b, double tolerance = TOLERANCE) {return fabs(a - b) <= tolerance;}
inline bool FNE(double a, double b, double tolerance = TOLERANCE) {return fabs(a - b) > tolerance;}
inline bool FEQZ(double a, double tolerance = TIGHT_TOLERANCE) {return fabs(a) <= tolerance;}
inline bool FNEZ(double a, double tolerance = TIGHT_TOLERANCE) {return fabs(a) > tolerance;}
#define PI 3.1415926535897932384626433832795e0
#define DegreesToRadians (PI / 180.0e0)
#define RadiansToDegrees (180.0e0 / PI)
#define NEARLY_ONE 0.99999999999e0
#define CPTANGENTTOL 1.0e-04 // normalised vector crossproduct tolerance sin A so A = .0057deg
#define TANTO -1
#define ANTITANTO 1
#define TANGENT 0
#define NEARINT 1
#define FARINT -1
#define LEFTINT 1
#define RIGHTINT -1
#define CFILLET 0 // corner fillet
#define CHAMFER 1 // chamfer
#define GEOFF_LEFT 1
#define NONE 0
#define GEOFF_RIGHT -1
#define LINEAR 0 // linear
#define ACW 1 // anti-clockwise
#define CW -1 // clockwise
const wchar_t* getMessage(const wchar_t* original, int messageGroup, int stringID);
const wchar_t* getMessage(const wchar_t* original); // dummy
void FAILURE(const wchar_t* str);
void FAILURE(const std::wstring& str);
enum MESSAGE_GROUPS {
GENERAL_MESSAGES,
GEOMETRY_ERROR_MESSAGES,
PARAMSPMP
};
enum GENERAL_MESSAGES {
MES_TITLE = 0,
MES_UNFINISHEDCODING,
MES_ERRORFILENAME,
MES_LOGFILE,
MES_LOGFILE1,
MES_P4CMENU,
MES_P4CMENUHINT
};
enum GEOMETRY_ERROR_MESSAGES{ // For geometry.lib
MES_DIFFSCALE = 1000,
MES_POINTONCENTRE,
MES_INVALIDARC,
MES_LOFTUNEQUALSPANCOUNT,
MES_EQUALSPANCOUNTFAILED,
MES_CANNOTTRIMSPAN,
MES_INDEXOUTOFRANGE,
MES_BAD_VERTEX_NUMBER,
MES_BAD_REF_OFFSET,
MES_BAD_SEC_OFFSET,
MES_ROLLINGBALL4AXIS_ERROR,
MES_INPUT_EQUALSPANCOUNT,
MES_INVALIDPLANE
};
// homogenous 4 x 4 Matrix class
class Matrix{
protected:
public:
double e[16];
bool m_unit; // true if unit matrix
int m_mirrored; // 1 if mirrored, 0 if not and -1 if unknown
public:
// constructors etc...
Matrix(); // create a unit matrix
Matrix(double m[16]); // from an array
Matrix(const Matrix& m); // copy constructor
~Matrix(){};
//operators
bool operator==(const Matrix &m)const;
bool operator!=(const Matrix &m)const { return !(*this == m);}
// methods
void Unit(); // unit matrix
void Get(double* p) const; // get the matrix into p
void Put(double*p); // put p[16] into matrix
void Translate(double x, double y, double z=0); // Translation
void Rotate(double sinang, double cosang, Vector3d *rotAxis); // Rotation about rotAxis
void Rotate(double angle, Vector3d *rotAxis); // Rotation about rotAxis
void Rotate(double sinang, double cosang, int Axis); // Rotation with cp & dp
void Rotate(double angle, int Axis); // Rotation with angle
void Scale(double scale); // Scale
void Scale(double scalex, double scaley, double scalez);
void Multiply(Matrix& m); // Multiply 2 Matrices
// void Transform(Point& p);
void Transform(double p0[3]) const; // Transform p0 thro' this matrix
void Transform(double p0[3], double p1[3]) const; // Transform p0 to p1 thro' this matrix
void Transform2d(double p0[2], double p1[2]) const; // Transform p0 to p1 thro' this matrix
int IsMirrored(); // true if matrix has a mirror transformation
int IsUnit(); // true if matrix is unit matrix
void GetTranslate(double& x, double& y, double& z) const; // get translation from matrix
void GetScale(double& sx, double& sy, double& sz) const; // get scale from matrix
bool GetScale(double& sx) const; // get scale from matrix (true if uniform scale)
void GetRotation(double& ax, double& ay, double& az) const; // get rotation from matrix
Matrix Inverse(); // inverts this matrix
};
extern Matrix UnitMatrix; // a Unit Matrix
// 2d Point class
class Point {
friend wostream& operator << (wostream& op, Point& p);
public:
bool ok; // true if this point is defined correctly
double x; // x value
double y; // y value
// constructors etc...
inline Point(){ ok=false;}; // Point p1
inline Point( double xord, double yord, bool okay = true) { // Point p1(10,30);
x = xord; y = yord; ok = okay;}
inline Point( const Point& p ) { // copy constructor Point p1(p2);
x = p.x; y = p.y; ok = p.ok;}
Point( const Point3d& p ); // copy constructor Point p1(p2);
Point(const Vector2d& v);
// operators
bool operator==(const Point &p)const;
bool operator!=(const Point &p)const { return !(*this == p);}
inline Point operator+(const Point &p)const{return Point(x + p.x, y + p.y);} // p0 = p1 + p2;
inline Point operator+=(const Point &p){return Point(x += p.x, y += p.y);} // p0 += p1;
Point operator+(const Vector2d &v)const; // p1 = p0 + v0;
// destructor
//~Point(){};
// methods
Point Transform(const Matrix& m); // transform point
double Dist(const Point& p)const; // distance between 2 points
double DistSq(const Point& p)const; // distance squared
double Dist(const CLine& cl)const; // distance p to cl
Point Mid(const Point& p, double factor=.5)const; // mid point
void get(double xyz[2]) {xyz[0] = x; xyz[1] = y;} // return to array
};
#define INVALID_POINT Point(9.9999999e50, 0, false)
#define INVALID_POINT3D Point3d(9.9999999e50, 0, 0, false)
#define INVALID_CLINE CLine(INVALID_POINT, 1, 0, false)
#define INVALID_CIRCLE Circle(INVALID_POINT, 0, false)
// 3d point class
class Point3d {
friend wostream& operator <<(wostream& op, Point3d& p);
public:
// bool ok; // true if this point is defined correctly
double x; // x value
double y; // y value
double z; // z value
// constructors
inline Point3d(){};// {z=0; /*ok=false;*/}; // Point p1
inline Point3d(const double* xyz) {x = xyz[0], y = xyz[1]; z = xyz[2];}
inline Point3d( double xord, double yord, double zord = 0/*, bool okay = true*/) { // Point p1(10,30.5);
x = xord; y = yord; z = zord;/* ok = okay;*/}
inline Point3d( const Point3d& p ) { // copy constructor Point p1(p2);
x = p.x; y = p.y; z = p.z;/* ok = p.ok;*/}
inline Point3d( const Point& p ) { // copy constructor Point p1(p2);
x = p.x; y = p.y; z = 0; /*ok = p.ok;*/}
inline Point3d( const Point& p, double zord ) { // copy constructor Point p1(p2, z);
x = p.x; y = p.y; z = zord;/* ok = p.ok;*/}
Point3d(const Vector3d& v);
// destructor
// ~Point3d();
// operators
bool operator==(const Point3d &p)const;
bool operator!=(const Point3d &p)const { return !(*this == p);}
Point3d operator+(const Vector3d &v)const; // p1 = p0 + v0;
// methods
#ifdef PEPSDLL
void ToPeps(int id, bool draw = true); // copy Point to Peps
#endif
Point3d Transform(const Matrix& m);
double Dist(const Point3d& p)const; // distance between 2 points
double DistSq(const Point3d& p)const; // distance squared between 2 points
Point3d Mid(const Point3d& p, double factor = 0.5)const; // midpoint
void get(double xyz[3]) {xyz[0] = x; xyz[1] = y; xyz[2] = z;}
double* getBuffer(){return &this->x;}; // returns ptr to data
const double* getBuffer()const{return &this->x;}; // returns ptr to data
};
// 2d vector class
class Vector2d{
friend wostream& operator <<(wostream& op, Vector2d& v);
private:
double dx, dy;
public:
// constructors
Vector2d() {};
inline Vector2d(const Vector2d &v) { dx = v.dx; dy = v.dy;}
Vector2d(const Vector3d &v); // careful
inline Vector2d(double x, double y) {dx = x, dy = y;}
inline Vector2d(const Point& p0, const Point& p1) {dx = p1.x - p0.x; dy = p1.y - p0.y;}
inline Vector2d(const Point *p0, const Point *p1) {dx = p1->x - p0->x; dy = p1->y - p0->y;}
inline Vector2d(const Point& p) { dx = p.x; dy = p.y;} // from 0,0 to p
inline Vector2d(double angle) {dx = cos(angle *= DegreesToRadians); dy = sin(angle);} // constructs a vector from an angle (0° - 360°)
// operators
inline const Vector2d& operator=(const Vector2d &v){dx = v.dx; dy = v.dy; return *this;} // v1 = v2;
inline Vector2d operator+(const Vector2d &v)const{return Vector2d(dx + v.dx, dy + v.dy);} // v2 = v0 + v1;
inline Point operator+(const Point &p)const{return Point(this->dx + p.x, this->dy + p.y);} // p1 = v0 + p0;
inline Vector2d operator+(const double d){ return Vector2d(dx + d, dy + d); };
inline const Vector2d& operator+=(const Vector2d &v){dx += v.dx; dy += v.dy; return *this;} // v1 += v0;
inline Vector2d operator-(const Vector2d &v)const{return Vector2d( dx - v.dx, dy - v.dy);} // v2 = v0 - v1;
inline const Vector2d& operator-=(const Vector2d &v){dx -= v.dx; dy -= v.dy; return *this;} // v1 -= v0;
inline Vector2d operator-(const double d){ return Vector2d(dx - d, dy - d); };
inline const Vector2d operator-(void)const{return Vector2d(-dx, -dy);} // v1 = -v0; (unary minus)
inline const double operator*(const Vector2d &v)const{return (dx * v.dx + dy * v.dy);} // dot product m0.m1.cos a = v0 * v1
inline Vector2d operator*(double c)const{return Vector2d(dx*c, dy*c);} // scalar product
inline const Vector2d& operator*=(double c){dx *= c; dy *= c; return *this;} // scalar product
inline Vector2d operator*(int c)const{return Vector2d(dx*(double)c, dy*(double)c);} // scalar product
inline const double operator^(const Vector2d &v)const{return (dx * v.dy - dy * v.dx);} // cross product m0.m1.sin a = v0 ^ v1
inline Vector2d operator~(void)const{return Vector2d(-dy, dx);} // perp to left
bool operator==(const Vector2d &v)const; // v1 == v2
inline bool operator!=(const Vector2d &v)const { return !(*this == v);} // v1 != v2
// methods
void get(double xyz[2]) {xyz[0] = dx; xyz[1] = dy;} // return to array
inline double getx()const{return dx;}
inline double gety()const{return dy;}
inline void putx(double x){dx = x;}
inline void puty(double y){dy = y;}
double normalise()
{double m = magnitude(); if(m < TIGHT_TOLERANCE) {dx=dy=0; return 0;} dx/=m; dy/=m; return m;} // normalise & returns magnitude
inline double magnitudesqd(void)const{return(dx * dx + dy * dy);} // magnitude squared
inline double magnitude(void)const{return(sqrt(magnitudesqd()));} // magnitude
void Rotate(double cosa, double sina){ // rotate vector by angle
double temp = -dy * sina + dx * cosa;
dy = dx * sina + cosa * dy;
dx = temp;
}
inline void Rotate(double angle) { if(FEQZ(angle) == true) return; Rotate(cos(angle), sin(angle));}
void Transform( const Matrix& m); // transform vector
// destructor
//~Vector2d(){}
};
// 3d vector class
class Vector3d{
friend wostream& operator <<(wostream& op, Vector3d& v);
private:
double dx, dy, dz;
public:
// constructors
Vector3d() {};
Vector3d(const Vector3d &v) { dx = v.dx; dy = v.dy; dz = v.dz;}
Vector3d(double x, double y, double z = 0) {dx = x, dy = y; dz = z;}
Vector3d(const double* x) {dx = x[0], dy = x[1]; dz = x[2];}
Vector3d(const double* x0, const double* x1) {dx = x1[0] - x0[0], dy = x1[1] - x0[1]; dz = x1[2] - x0[2];}
Vector3d(const Point3d& p0, const Point3d& p1) {dx = p1.x - p0.x; dy = p1.y - p0.y; dz = p1.z - p0.z;}
Vector3d(const Point3d& p) { dx = p.x; dy = p.y; dz = p.z;} // from 0,0,0 to p
Vector3d(const Vector2d& v) {dx = v.getx(); dy = v.gety(); dz = 0;}
// operators
bool operator==(const Vector3d &v)const { return(FEQ(dx, v.dx, UNIT_VECTOR_TOLERANCE) && FEQ(dy, v.dy, UNIT_VECTOR_TOLERANCE) && FEQ(dz, v.dz, UNIT_VECTOR_TOLERANCE)); } // v1 == v2 (unit only!)
bool operator!=(const Vector3d &v)const { return (!(*this == v)); } // v1 != v2
const Vector3d& operator=(const Vector3d &v){dx = v.dx; dy = v.dy; dz = v.dz;return *this;} // v1 = v2;
// const Vector3d& operator=(const Vector2d &v){dx = v.getx(); dy = v.gety(); dz = 0.0;return *this;} // v1 = v2;
inline Point3d operator+(const Point3d &p)const{return Point3d(dx + p.x, dy + p.y, dz + p.z);} // p1 = v0 + p0;
Vector3d operator+(const Vector3d &v)const{return Vector3d(dx + v.dx, dy + v.dy, dz + v.dz);} // v2 = v0 + v1;
const Vector3d& operator+=(const Vector3d &v){dx += v.dx; dy += v.dy; dz += v.dz; return *this;} // v1 += v0;
Vector3d operator-(const Vector3d &v)const{return Vector3d( dx - v.dx, dy - v.dy, dz - v.dz);} // v2 = v0 - v1;
const Vector3d& operator-=(const Vector3d &v){
dx -= v.dx; dy -= v.dy; dz -= v.dz; return *this;} // v1 -= v0;
const Vector3d operator-(void)const{return Vector3d(-dx, -dy, -dz);} // v1 = -v0; (unary minus)
const double operator*(const Vector3d &v)const{return (dx * v.dx + dy * v.dy + dz * v.dz);} // dot product m0 m1 cos a = v0 * v1
const Vector3d& operator*=(double c){dx *= c; dy *= c; dz *= c; return *this;} // scalar products
friend const Vector3d operator*(const Vector3d &v, double c){return Vector3d(v.dx*c, v.dy*c, v.dz*c);}
friend const Vector3d operator*(double c, const Vector3d &v){return Vector3d(v.dx*c, v.dy*c, v.dz*c);}
friend const Vector3d operator/(const Vector3d &v, double c){return Vector3d(v.dx/c, v.dy/c, v.dz/c);}
const Vector3d operator^(const Vector3d &v)const{
return Vector3d(dy * v.dz - dz * v.dy, dz * v.dx - dx * v.dz, dx * v.dy - dy * v.dx);} // cross product vector
// = the vector perp to the plane of the 2 vectors
// the z component magnitude is m0.m1.sin a
// methods
inline void get(double xyz[3])const {xyz[0] = dx; xyz[1] = dy; xyz[2] = dz;} // return to array
inline double getx()const{return dx;}
inline double gety()const{return dy;}
inline double getz()const{return dz;}
inline void putx(double x){dx = x;}
inline void puty(double y){dy = y;}
inline void putz(double z){dz = z;}
double normalise(){double m = magnitude(); if(m < 1.0e-09) {dx=dy=dz=0; return 0;} dx/=m; dy/=m; dz/=m; // normalise & returns magnitude
return m;}
inline double magnitude(void)const{return(sqrt(dx * dx + dy * dy + dz * dz));} // magnitude
inline double magnitudeSq(void)const{return(dx * dx + dy * dy + dz * dz);} // magnitude squared
void Transform( const Matrix& m); // transform vector
void arbitrary_axes(Vector3d& x, Vector3d& y);
int setCartesianAxes(Vector3d& b, Vector3d& c);
double* getBuffer(){return &this->dx;}; // returns ptr to data
const double* getBuffer()const{return &this->dx;}; // returns ptr to data
// destructor
//~Vector3d(){}
};
#define ORIGIN Point3d(0,0,0)
#define NULL_VECTOR Vector3d(0,0,0)
#define Z_VECTOR Vector3d(0,0,1)
#define Y_VECTOR Vector3d(0,1,0)
#define X_VECTOR Vector3d(1,0,0)
// 2D cline x = x0 + t * dx; y = y0 + t * dy
class CLine{
friend wostream& operator <<(wostream& op, CLine& cl);
public:
bool ok;
Point p;
Vector2d v;
// constructors
inline CLine() {ok = false;};
inline CLine(const Point& p0, double dx, double dy, bool normalise = true){ p = p0; v = Vector2d(dx, dy); if(normalise) Normalise();};
inline CLine(const Point& p0, const Vector2d& v0, bool normalise = true) {p = p0; v = v0; if(normalise) Normalise();};
inline CLine( const CLine& s ) {p = s.p; v = s.v;}; // copy constructor CLine s1(s2);
inline CLine(const Point& p0, const Point& p1) {p = p0; v = Vector2d(p0, p1); Normalise();};
CLine(const Span& sp);
// operators
const CLine operator~(void);// perp to left
const CLine operator=(const Point& p0){p.x=p0.x; p.y=p0.y; return *this;}; // s = p;
// methods
double c(); // returns c
void Normalise(); // normalise dx,dy
#ifdef PEPSDLL
void ToPeps(int id, bool draw = true); // to Peps
void DelPeps(int id); // delete Peps CLine
#endif
CLine Transform(Matrix& m); // transform a CLine
Point Intof(const CLine& s); // intersection of 2 clines
Point Intof(int NF, const Circle& c); // intersection of cline & circle
Point Intof(int NF, const Circle& c, Point& otherInters); double Dist(const Point& p1)const; // ditto & other intersection
CLine Bisector(const CLine& s); // Bisector of 2 Clines
// destructor
// ~CLine();
};
#define HORIZ_CLINE CLine(geoff_geometry::Point(0,0), 1.0, 0.0, true)
// 2D circle
class Circle{
friend wostream& operator <<(wostream& op, Circle& c);
public:
bool ok;
Point pc;
double radius;
// constructors etc...
inline Circle() {ok = false;};
Circle( const Point& p, double r, bool okay = true); // Circle c1(Point(10,30), 20);
Circle( const Point& p, const Point& pc); // Circle c1(p[222], p[223]);
Circle( const Circle& c ){*this = c;} // copy constructor Circle c1(c2);
Circle( const Span& sp); // constructor
// methods
#ifdef PEPSDLL
void ToPeps(int id, bool draw = true); // to Peps
void DelPeps(int id); // delete Peps Circle
#endif
bool operator==(const Circle &c)const; // c == cc
bool operator!=(const Circle &c)const { return !(*this == c);}
Circle Transform(Matrix& m); // transform a Circle
Point Intof(int LR, const Circle& c1); // intof 2 circles
Point Intof(int LR, const Circle& c1, Point& otherInters); // intof 2 circles, (returns the other intersection)
int Intof(const Circle& c1, Point& leftInters, Point& rightInters); // intof 2 circles (returns number of intersections & left/right inters)
CLine Tanto(int AT, double angle, const CLine& s0)const; // a cline tanto this circle at angle
// ~Circle(); // destructor
};
// 2d box class
class Box{
public:
Point min;
Point max;
bool ok;
Box() { min.x = min.y = 1.0e61; max.x = max.y = -1.0e61; ok = false;};
Box(Point& pmin, Point& pmax) { min = pmin; max = pmax; ok = true;};
bool outside(const Box& b)const; // returns true if box is outside box
void combine(const Box& b); // combines this with b
};
// 3d box class
class Box3d{
public:
Point3d min;
Point3d max;
bool ok;
Box3d() { min.x = min.y = min.z = 1.0e61; max.x = max.y = max.z = -1.0e61; ok = false;};
Box3d(const Point3d& pmin, const Point3d& pmax) { min = pmin; max = pmax; ok = true;};
bool outside(const Box3d& b)const; // returns true if box is outside box
void combine(const Box3d& b); // combines this with b
};
inline void MinMax(const Point& p, Point& pmin, Point& pmax) {
if(p.x > pmax.x) pmax.x = p.x;
if(p.y > pmax.y) pmax.y = p.y;
if(p.x < pmin.x) pmin.x = p.x;
if(p.y < pmin.y) pmin.y = p.y;
};
inline void MinMax(const Point3d& p, Point3d& pmin, Point3d& pmax) {
if(p.x > pmax.x) pmax.x = p.x;
if(p.y > pmax.y) pmax.y = p.y;
if(p.z > pmax.z) pmax.z = p.z;
if(p.x < pmin.x) pmin.x = p.x;
if(p.y < pmin.y) pmin.y = p.y;
if(p.z < pmin.z) pmin.z = p.z;
};
// 2D line arc span
class Span{
friend wostream& operator <<(wostream& op, Span& span);
public:
Point p0; // start
Point p1; // end
Point pc; // centre
int dir; // arc direction (CW or ACW or 0 for straight)
int ID; // ID (for offset in wire - stores spanID etc. from original kurve)
bool ok;
bool returnSpanProperties; // set if properties below are set
Vector2d vs; // direction at start or for straight
Vector2d ve; // direction at span end
double length; // span length
double radius; // arc radius
double angle; // included arc angle ( now arc is parameterised start -> start + angle
Box box; // span box
bool NullSpan; // true if small span
// methods
void SetProperties(bool returnProperties); // set span properties
Span Offset(double offset); // offset span method
int Split(double tolerance); // returns number of splits
void SplitMatrix(int num_vectors, Matrix* matrix); // returns incremental matrix from split
void minmax(Box& box, bool start = true); // minmax of span
void minmax(Point& pmin, Point& pmax, bool start = true); // minmax of span
int Intof(const Span& sp, Point& pInt1, Point& pInt2, double t[4])const;
void Transform(const Matrix& m, bool setprops = true);
Point Near(const Point& p)const; // returns the near point to span from p (on or off)
Point NearOn(const Point& p)const; // returns the near point to span from p (on span)
Point Mid()const; // midpoint of a span
Point MidPerim(double d)const; // interior point of Span (param 0 - d)
Point MidParam(double param)const; // interior point of Span (param 0 - 1)
bool OnSpan(const Point& p)const; // tests if p is on sp *** FAST TEST p MUST LIE on unbounded span
bool OnSpan(const Point& p, double* t)const; // tests if p is on sp *** FAST TEST p MUST LIE on unbounded span
bool JoinSeparateSpans(Span& sp);
Span BlendTwoSpans(Span& sp2, double radius, double maxt); // Blends 2 Spans
bool isJoinable(const Span& sp)const; // is this & sp joinable to 1 span?
Vector2d GetVector(double fraction)const; // the direction along the span, 0.0 for start, 1.0 for end
// constructor
Span() {ID = 0; ok = false;};
Span(int spandir, const Point& pn, const Point& pf, const Point& c) { dir = spandir; p0 = pn, p1 = pf, pc = c; ID = 0; SetProperties(true); ok = p0.ok;};
// operators
// bool operator==(const Span &sp)const;
// bool operator!=(const Span &sp)const { return !(*this == sp);}
};
// general
double atn360(double dx, double dy); // angle 0 to 2pi
// distance functions
//double Dist(double px, double py, double p1x, double p1y); // diatance between 2 points (2d)
//double Dist(Point& p0, Point& p1); // distance between 2 points (3d)
//double Dist(CLine& s, Point& p1); // distance between cline & point
double Dist(const Point3d *p, const Vector3d *vl, const Point3d *pf); // distance from line (p, vl) and pf
double DistSq(const Point3d *p, const Vector3d *vl, const Point3d *pf); // distance squared from line (p, vl) and pf
double Dist(const Circle& c, const Point& p); // distance between c & p
double Dist(const Point& p0, const Circle& c, const Point& p1); // clockwise distance around c from p0 to p1
double Dist(const CLine& s, const Circle& c); // distance between line and circle
double Dist(const Circle& c0, const Circle& c1); // distance between 2 circles
double IncludedAngle(const Vector2d& v0, const Vector2d& v1, int dir = 1); // angle between 2 vectors
double IncludedAngle(const Vector3d& v0, const Vector3d& v1, const Vector3d& normal, int dir = 1);
inline double IncludedAngle(const CLine& s0, const CLine& s1, int dir = 1) { // angle between 2 Clines
return IncludedAngle(s0.v, s1.v, dir);
}
// point definitions
Point Mid(const Point& p0, const Point& p1, double factor = 0.5); //// midpoint
Point Mid(const Span& sp); //// midpoint of a span
Point Rel(const Point& p, double x, double y); // relative point
Point Polar(const Point& p, double angle, double r); // polar from this point
Point AtAngle(const Circle& c, double angle); // Point at angle on a circle
Point XonCLine(const CLine& s, double xval); // returns point that has X on this line
Point YonCLine(const CLine& s, double yval); // returns point that has Y on this line
Point Intof(const CLine& s0, const CLine& s1); //// intof 2 clines
Point Intof(int NF, const CLine& s, const Circle& c); //// intof of circle & a cline
Point Intof(int NF, const CLine& s, const Circle& c, Point& otherInters); //// intof of circle & a cline (returns the other intersection)
Point Intof(int LR, const Circle& c0, const Circle& c1); //// intof 2 circles
Point Intof(int LR, const Circle& c0, const Circle& c1, Point& otherInters); //// intof 2 circles, (returns the other intersection)
int Intof(const Circle& c0, const Circle& c1, Point& pLeft, Point& pRight); //// ditto
Point Along(const CLine& s, double d); // distance along Cline
Point Along(const CLine& s, double d, const Point& p); // distance along Cline from point
Point Around(const Circle& c, double d, const Point& p); // distance around a circle from point
Point On(const CLine& s, const Point& p); // returns a point on s nearest to p
Point On(const Circle& c, const Point& p); // returns a point on c nearest to p
// cline definitons
CLine AtAngle(double angle, const Point& p, const CLine& s = HORIZ_CLINE); // cline at angle to line thro' point
CLine Tanto(int AT, const Circle& c, double angle, const CLine& s0 = HORIZ_CLINE);//// cline tanto circle at angle to optional cline
CLine Tanto(int AT, const Circle& c, const Point& p); // cline tanto circle thro' a point
CLine Tanto(int AT0, const Circle& c0, int AT1, const Circle& c1); // cline tanto 2 circles
CLine Normal(const CLine& s); // noirmal to cline
CLine Normal(const CLine& s, const Point& p); // normal to cline thro' p
CLine Parallel(int LR, const CLine& s, double distance); // parallel to cline by distance
CLine Parallel(const CLine& cl, const Point& p); // parallel to cline thro' a point
// circle definitions
Circle Thro(const Point& p0, const Point& p1); // circle thro 2 points (diametric)
Circle Thro(const Point& p0, const Point& p1, const Point& p2); // circle thro 3 points
Circle Tanto(int NF, const CLine& s0, const Point& p, double rad); // circle tanto a CLine thro' a point with radius
Circle Thro(int LR, const Point& p0, const Point& p1, double rad); // circle thro' 2 points with radius
Circle Tanto(int AT1, const CLine& s1, int AT2, const CLine& s2, double rad); // circle tanto 2 clines with radius
Circle Tanto(int AT1, const CLine& s1, int AT2, const CLine& s2, int AT3, const CLine& s3); // circle tanto 3 clines
Circle Tanto(int LR, int AT, const Circle& c, const Point& p, double rad); // circle tanto circle & thro' a point
Circle Tanto(int NF, int AT0, const CLine& s0, int AT1, const Circle& c1, double rad);// circle tanto cline & circle with radius
Circle Tanto(int LR, int AT0, const Circle& c0, int AT1, const Circle& c1, double rad);// circle tanto 2 circles with radius
Circle Tanto(int LR, int AT1 , const Circle& c1 , int AT2 , const Circle& c2, int AT3 , const Circle c3); // tanto 3 circles
int apolloniusProblem(int AT1 , const Circle& c1 , int AT2 , const Circle& c2, int AT3 , const Circle& c3, Circle& Solution1, Circle& Solution2);
int apolloniusProblem(int AT1 , const Circle& c1 , int AT2 , const Circle& c2, int AT3 , const CLine& cl3, Circle& Solution1, Circle& Solution2);
int apolloniusProblem(int AT1 , const Circle& c1 , int AT2 , const CLine& cl2, int AT3 , const CLine& cl3, Circle& Solution1, Circle& Solution2);
// Circle Tanto(int AT0, int NF, int AT1, CLine s1, int AT2, CLine s2); // circle tanto circle, and 2 clines
Circle Parallel(int LR, const Circle& c, double distance); // parallel to circle by a distance
// misc
inline double Radians(double degrees) {return degrees * PI / 180;}
inline double Degrees(double radians) { return radians * 180 / PI;}
int quadratic(double a, double b, double c, double& x0, double& x1); // solve quadratic
int corner(const Vector2d& v0, const Vector2d& v1, double cpTol = CPTANGENTTOL); // corner (TANGENT, LEFT, RIGHT)
inline int corner(const Span& span, const Span& next, double cpTol = CPTANGENTTOL) {
return corner((Vector2d)span.ve, (Vector2d)next.vs, cpTol);}
Line IsPtsLine(const double* a, int n, double tolerance, double* deviation);
// Span3d IsPtsSpan3d(const double* a, int n, double tolerance, double* deviation);
class Plane {
friend wostream& operator <<(wostream& op, Plane& pl);
public: // ax + by + cz + d = 0
bool ok;
double d; // distance of plane to origin
Vector3d normal; // normal to plane a = n.dx, b = n.dy, c = n.dz
// constructors
Plane(){ok = false;};
Plane(double dist, const Vector3d& n);
Plane(const Point3d& p0, const Point3d& p1, const Point3d& p2);
Plane(const Point3d& p0, const Vector3d& n, bool normalise = true);
// methods
double Dist(const Point3d& p)const; // signed distance of point to plane
bool Intof(const Line& l, Point3d& intof, double& t)const; // intersection of plane & line (0 >= t <= 1 if intersect within line)
bool Intof(const Plane& pl, Line& intof)const; // intersection of 2 planes
bool Intof(const Plane& pl0, const Plane& pl1, Point3d& intof)const; // intersection of 3 planes
Point3d Near(const Point3d& p)const; // returns near point to p on the plane
void Mirrored(Matrix* m); // returns a matrix for a mirror about this
};
#define SPANSTORAGE 32 // lessens number of object pointers
class spVertex {
friend wostream& operator <<(wostream& op, spVertex& sp);
public:
int type;
int spanid;
Point p;
Point pc;
spVertex(){};
spVertex(int t, const Point& point, const Point& centre): type(t), spanid(0), p(point), pc(centre){};
bool operator==(spVertex &spv){
// vertex == spvertex (vertex check - doesn't check spannid!)
if(this->type != spv.type) return false;
if(this->p != spv.p) return false;
if(this->type != LINEAR) {
if(this->pc != spv.pc) return false;
}
return true;
}
bool operator!=(spVertex &spv){ return !(*this == spv);}
};
class SpanDataObject {
// holds everything needed for Post-Processing/Simulation
public:
int method; // holds method type
SpanDataObject(int meth){method = meth;};
SpanDataObject(const SpanDataObject* obj){method = obj->method;};
};
class SpanVertex{
public:
int type[SPANSTORAGE]; // LINEAR CW or ACW // 0 straight (cw = -1 (T) acw = 1 (A) )
int spanid[SPANSTORAGE]; // identification (eg wire offset span info)
const SpanDataObject* index[SPANSTORAGE]; // other - pointer to
double x[SPANSTORAGE], y[SPANSTORAGE]; // vertex
double xc[SPANSTORAGE], yc[SPANSTORAGE]; // centre of arc
public:
// methods
void Add(int offset, int type, const Point& p0, const Point& pc, int ID = UNMARKED);
const SpanDataObject* GetIndex(int offset)const;
void AddSpanID(int offset, int ID);
SpanVertex();
~SpanVertex();
const SpanVertex& operator= (const SpanVertex& spv );
void Add(int offset, const SpanDataObject* Index );
const SpanDataObject* Get(int offset);
int Get(int offset, Point& pe, Point& pc);
int GetSpanID(int offset);
};
#ifdef WIN32
#pragma warning(disable:4522)
#endif
class Kurve : public Matrix{
friend wofstream& operator << (wofstream& op, Kurve& k);
friend wifstream& operator >> (wifstream& op, Kurve& k);
protected:
vector<SpanVertex*> m_spans;
bool m_started;
int m_nVertices; // number of vertices in Kurve
bool m_isReversed; // true if get spans reversed
public:
// for comparing kurves
struct spanCompare {
int dir; // LINEAR, CW or ACW
double length; // length of the span
double cp; // cross-product to next span (sina)
double dp;
};
// constructors etc...
Kurve() {
m_started = false;
m_nVertices = 0;
m_isReversed = false;
};
Kurve(const Kurve& k0);
const Kurve& operator= (const Kurve& k );
const Kurve& operator=(const Matrix &m);
bool operator==(const Kurve &k)const; // k == kk (vertex check)
bool operator!=(const Kurve &k)const { return !(*this == k);}
// destructor
~Kurve();
// methods
inline int nSpans( )const {return (m_nVertices)? m_nVertices - 1 : 0;} // returns the number of spans
bool Closed()const; // returns true if kurve is closed
inline bool Started()const {return m_started;};
void FullCircle(int dir, const Point& c, double radius); // make a full circle
void Start(); // start a new kurve
void Start(const Point& p); // start a new kurve with start point
bool Add(const spVertex& spv, bool AddNullSpans = true); // add a vertex
void Get(int vertex, spVertex& spv) const; // get a vertex
bool Add(const Span& sp, bool AddNullSpans = true); // add a span
bool Add(int type, const Point& p0, const Point& pc, bool AddNullSpans = true); // a span
void AddSpanID(int ID);
bool Add(const Point& p0, bool AddNullSpans = true); // linear
void Add(); // add a null span
void Add(const Kurve* k, bool AddNullSpans = true); // a kurve
void StoreAllSpans(std::vector<Span>& kSpans)const; // store all kurve spans in array, normally when fast access is reqd
void Clear(); // remove all the spans
void Replace(int vertexnumber, const spVertex& spv);
void Replace(int vertexnumber, int type, const Point& p, const Point& pc, int ID = UNMARKED);
int GetSpanID(int spanVertexNumber) const; // for spanID (wire offset)
int Get(int spanVertexNumber, Point& p, Point& pc) const;
void Get(std::vector<Span> *all, bool ignoreNullSpans) const; // get all spans to vector
int Get(int spanVertexNumber, Point3d& p, Point3d& pc) const
{ Point p2d, pc2d; int d = Get(spanVertexNumber, p2d, pc2d); p = p2d; pc = pc2d; return d;}
int Get(int spannumber, Span& sp, bool returnSpanProperties = false, bool transform = false) const;
// int Get(int spannumber, Span3d& sp, bool returnSpanProperties = false, bool transform = false) const;
void Get(Point &ps,Point &pe) const; // returns the start- and endpoint of the kurve
const SpanDataObject* GetIndex(int vertexNumber)const;
inline double GetLength()const{ return Perim();}; // returns the length of a kurve
void minmax(Point& pmin, Point& pmax); // minmax of span
void minmax(Box& b);
Point NearToVertex(const Point& p, int& nearSpanNumber)const;
Point NearToVertex(const Point& p)const { int nearSpanNumber; return NearToVertex(p, nearSpanNumber);};
Point Near(const Point& p, int& nearSpanNumber)const;
Point Near(const Point& p) const{ int nearSpanNumber; return Near(p, nearSpanNumber);};
double Perim()const; // perimeter of kurve
double Area()const; // area of closed kurve
void Reverse(); // reverse kurve direction - obsolete
bool Reverse(bool isReversed) { // reverse kurve direction - later better method
bool tmp = m_isReversed;
m_isReversed = isReversed;
return tmp;
};
int Reduce(double tolerance); // reduce spans which are in tolerance
int Offset(vector <Kurve*> &OffsetKurves, double offset, int direction, int method, int& ret)const; // offset methods
int OffsetMethod1(Kurve& kOffset, double off, int direction, int method, int& ret)const;
int OffsetISOMethod(Kurve& kOffset, double off, int direction, bool BlendAll)const; // special offset (ISO radius - no span elimination)
int Intof(const Span& sp, vector<Point>& p)const; // intof span
int Intof(const Kurve&k, vector<Point>& p)const; // intof kurve
bool Compare(const Kurve* k, Matrix* m, bool bAllowMirror = true)const; // compare 2 Kurves
void ChangeStart(const Point *pNewStart, int startSpanno); // change the Kurve's startpoint
void ChangeEnd(const Point *pNewEnd, int endSpanno); // change the Kurve's endpoint
private:
bool compareKurves(const std::vector<struct spanCompare> &first, const std::vector<struct spanCompare> &second, int &nOffset/*, Kurve *k, Matrix *m*/)const;
bool calculateMatrix(const Kurve *k, Matrix *m, int nOffset, bool bMirror = false)const;
public:
void AddIndex(int vertexNumber, const SpanDataObject* data);
bool Split(double MaximumRadius, double reslution); // split arcs larger than MaximumRadius to resoultion
int IntExtWire( Kurve& kSec, double Ref, double Sec, double height, Kurve* kOut); // interpolate / extrapolate a mid height kurve (wire)
void SetZ(double z) { e[11] = z; if(fabs(z) > 1.0e-6) m_unit = false;} // assigns kurve to fixed height (wire)
void Part(int startVertex, int EndVertex, Kurve *part);
Kurve Part(int fromSpanno, const Point& fromPt, int toSpanno, const Point& toPt); // make a Part Kurve
int Break(double atParam, const Kurve *secInput, Kurve *refOut, Kurve *secOut);// break kurve perimeter parameterisation with synchronised Kurve (wire)
void Part(double fromParam, double toParam, const Kurve *secInput, Kurve *refOut, Kurve *secOut);// part kurve perimeter parameterisation with synchronised Kurve (wire)
Kurve Part(double fromParam, double toParam); // part kurve perimeter parameterisation
void AddSections(const Kurve* k, bool endOfSection); // special add kurves for rollingball
void AddEllipse(int dir, const Point& pStart, const Point& pEnd, const Point& pCentre, const Vector2d& majorAxis, double majorRadius, double minorRadius, double tolerance);
// void Kurve::AddEllipse(int dir, Plane *plEllipse, Vector3d *cylAxis, Point3d *cylCentre, double cylradius, Point3d *pStart, Point3d *pEnd, double tolerance); /// elliptical curve - biarc in tolerance
void Spiral(const Point& centre, double startAngle, double startRadius, double radiusRisePerRevolution, double endRadius);
#ifdef PARASOLID
int ToPKcurve(PK_CURVE_t *curves, PK_INTERVAL_t *ranges, int start_spanno, int n_spans); // Convert to PK Curve
PK_BODY_t ToPKwire(); // Convert to PK Wire Body
PK_BODY_t ToPKwire(int start_spanno, int n_spans);
PK_BODY_t ToPKsheet( ); // Convert to PK Sheet Body
PK_BODY_t ToPKextrudedBody(PK_VECTOR1_t path, bool solidbody = true);
// Convert to PK Body (open kurve >> sheet)
PK_BODY_t ToPKlofted_sheet_body(Kurve &sec); // Convert 2 kurves to lofted sheet body
PK_BODY_t ToPKlofted_thickened_body(Kurve &sec, double thickness);
#endif
};
#ifdef WIN32
#pragma warning(default:4522)
#endif
void tangential_arc(const Point &p0, const Point &p1, const Vector2d &v0, Point &c, int &dir);
int EqualiseSpanCount(Kurve& k1, Kurve& k2, Kurve& k1equal, Kurve& k2equal, bool equalise_same_span_count); // span count equalisation
void EqualiseSpanCountAfterOffset(Kurve& k1, Kurve&k2, Kurve& k1Out, Kurve& k2Out);// span equalisation after offset
void EqualiseSpanCountAfterOffsetFromRollAround(Kurve& k1, Kurve&k2, Kurve& k1Out, Kurve& k2Out/*, double offset, int arc_direction*/);// span equalisation after offset
Point IntofIso(Span& one, Span& two, Span& three); // for iso blend radiuses - calc intersection
inline double CPTOL(double offset, double maxOffset) {
// this returns a suitable tolerance for a cross product
// the cp for normalised vectors is the sin of the included angle between the vectors
//
// this function takes the machine resolution from RESOLUTION
offset = fabs(offset);
if(offset <= RESOLUTION) offset = maxOffset; // no known offset so guess one from the application
return RESOLUTION / offset;
}
// finite Span routines
int Intof(const Span& sp0 , const Span& sp1, Point& p0, Point& p1, double t[4]);
int LineLineIntof(const Span& L0 , const Span& L1, Point& p, double t[2]);
int LineArcIntof(const Span& line, const Span& arc, Point& p0, Point& p1, double t[4]);
int ArcArcIntof(const Span& arc0, const Span& arc1, Point& pLeft, Point& pRight, double t[4]);
bool OnSpan(const Span& sp, const Point& p);
bool OnSpan(const Span& sp, const Point& p, bool nearPoints, Point& pNear, Point& pOnSpan); // function returns true if pNear == pOnSpan
// pNear (nearest on unbound span)
// pOnSpan (nearest on finite span)
int Intof(const Line& v0, const Line& v1, Point3d& intof); // intof 2 lines
double Dist(const Line& l, const Point3d& p, Point3d& pnear, double& t); // distance from a point to a line
Point3d Near(const Line& l, const Point3d& p, double& t ); // near point to a line & t in 0-length range
double Dist(const Span& sp, const Point& p , Point& pnear ); // distance from p to sp, nearpoint returned as pnear
// Kurve splineUsingBiarc(CLine& cl0, CLine& cl1, std::vector<pts>);
int biarc(CLine& cl0, CLine& cl1, Span* sp0, Span* sp1 );
// 3d line segment
class Line{
public:
Point3d p0; // start
Vector3d v; // vector (not normalised)
double length; // line length
Box3d box;
bool ok;
// constructors
Line() {ok = false;};
Line(const Point3d& p0, const Vector3d& v0, bool boxed = true);
Line(const Point3d& p0, const Point3d& p1);
Line(const Span& sp);
// methods
void minmax();
Point3d Near(const Point3d& p, double& t)const; // near point to line from point (0 >= t <= 1) in range
int Intof(const Line& l, Point3d& intof)const {return geoff_geometry::Intof(*this, l, intof);}; // intof 2 lines
bool atZ(double z, Point3d& p)const; // returns p at z on line
bool Shortest(const Line& l2, Line& lshort, double& t1, double& t2)const; // calculate shortest line between this & l2
};
class Triangle3d {
Point3d vert1; // first vertex
Point3d vert2; // second vertex
Point3d vert3; // third vertex
Vector3d v0; // vector from vert1 to vert2
Vector3d v1; // vector from vert1 to vert3
bool ok;
Box3d box; // box around triangle
public:
// constructor
Triangle3d(){ ok = false;};
Triangle3d(const Point3d& vert1, const Point3d& vert2, const Point3d& vert3);
// methods
bool Intof(const Line& l, Point3d& intof)const; // returns intersection triangle to line
};
} // End namespace geoff_geometry