00001 #ifndef PH_GEOMETRY2D_H
00002 #define PH_GEOMETRY2D_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <Base/Affine.h>
00040 #include <FileIO/FIDocScene.h>
00041 #include <SceneGraph/SGScene.h>
00042 #include <vector>
00043
00044 using namespace PTM;
00045 namespace Spr{;
00046
00047
00048 namespace PHG2{
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 static const double Epsilon = 1.0e-5;
00065
00066
00067
00068 enum DOF{
00069 T0R0,
00070 T0R1,
00071 T1R0,
00072 T2R0,
00073 T2R1
00074 };
00075
00076
00077 enum Result{
00078 AGAIN,
00079 SOLVED,
00080 NEW,
00081 ILLPOSED,
00082 OVER,
00083 REDUNDANT,
00084 ERROR
00085 };
00086
00087 typedef float Float;
00088 typedef Vec2f Vector2;
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 DEF_RECORD(XVector2, {
00099 GUID Guid(){return WBGuid("ec045bba-b265-4511-973d-500656055f40");}
00100 Float x;
00101 Float y;
00102 });
00103
00104
00105
00106
00107
00108
00109 DEF_RECORD(XGeometry2DEngine, {
00110 GUID Guid(){ return WBGuid("a59cd5af-d032-421f-a3ce-24920fd84222"); }
00111 });
00112
00113 DEF_RECORD(XPointToPoint2D, {
00114 GUID Guid(){ return WBGuid("e4fa6c65-eddb-473c-96e9-9300d63875b0"); }
00115 Vector2 point_l;
00116 Vector2 point_r;
00117 });
00118
00119 DEF_RECORD(XPointToLine2D, {
00120 GUID Guid(){ return WBGuid("1b0bbd07-7d79-4f95-ae7a-660e8fe05ed5"); }
00121 Vector2 point;
00122 Vector2 line0;
00123 Vector2 line1;
00124 });
00125
00126 DEF_RECORD(XPointToArc2D, {
00127 GUID Guid(){ return WBGuid("6669a0c5-6ad0-4f58-84e5-98673b2cd03d"); }
00128 Vector2 point;
00129 Vector2 center;
00130 Float radius;
00131 Float limit0;
00132 Float limit1;
00133 });
00134
00135 DEF_RECORD(XLineToLine2D, {
00136 GUID Guid(){ return WBGuid("2e675bc7-c8a2-42bd-9d18-02e60e8f8b6a"); }
00137 Vector2 line0_l;
00138 Vector2 line1_l;
00139 Vector2 line0_r;
00140 Vector2 line1_r;
00141 });
00142
00143 DEF_RECORD(XLineToArc2D, {
00144 GUID Guid(){ return WBGuid("f9e509e9-3010-41dd-9cf1-c9c6f6fb76ae"); }
00145 Vector2 line0;
00146 Vector2 line1;
00147 Vector2 center;
00148 Float radius;
00149 Float limit0;
00150 Float limit1;
00151 });
00152
00153 DEF_RECORD(XArcToArc2D, {
00154 GUID Guid(){ return WBGuid("41bc8040-7536-4bf2-b66d-da3f5a8f2ffc"); }
00155 Vector2 center_l;
00156 Float radius_l;
00157 Float limit0_l;
00158 Float limit1_l;
00159 Vector2 center_r;
00160 Float radius_r;
00161 Float limit0_r;
00162 Float limit1_r;
00163 });
00164
00165 DEF_RECORD(XParallel2D, {
00166 GUID Guid(){ return WBGuid("cfd3c326-485a-42b7-8311-63bbbf21c58c"); }
00167 Float dir_l;
00168 Float dir_r;
00169 });
00170
00171 DEF_RECORD(XAngle2D, {
00172 GUID Guid(){ return WBGuid("66cc9fe9-b9b6-46a8-9c04-6049a6c2b782"); }
00173 Float offset_l;
00174 Float offset_r;
00175 Float angle;
00176 });
00177
00178 DEF_RECORD(XFix2D, {
00179 GUID Guid(){ return WBGuid("8a3c63cf-639e-408f-8075-44c35f78c539"); }
00180 Vector2 offset;
00181 Float angle;
00182 });
00183
00184
00185 class Frame : public UTRefCount{
00186 public:
00187 UTRef<SGFrame> frame;
00188 DOF dof;
00189 Vec2d center;
00190 Vec2d range0, range1;
00191
00192 Vec2d position;
00193 double angle;
00194
00195
00196 Vec2d toWorld(const Vec2d& pl){
00197 return Matrix2d::Rot(angle) * pl + position;
00198 }
00199 Vec2d toLocal(const Vec2d& pw){
00200 return Matrix2d::Rot(-angle) * (pw - position);
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 Frame(SGFrame* f):frame(f){
00216 dof = T2R1;
00217 angle = 0.0;
00218 }
00219
00220 };
00221
00222
00223 class FrameList : public std::vector<UTRef<Frame> >{
00224 public:
00225 iterator find(SGFrame* fr){
00226 for(iterator it = begin(); it != end(); it++)
00227 if((*it)->frame == fr)
00228 return it;
00229 return end();
00230 }
00231
00232
00233
00234
00235
00236
00237
00238 };
00239
00240 }
00241
00242
00243
00244 class PHConstraintList2D;
00245 class PHConstraint2D : public SGObject{
00246 public:
00247
00248 SGOBJECTDEFABST(PHConstraint2D);
00249 virtual bool AddChildObject(SGObject* o, SGScene* s);
00250 virtual bool DelChildObject(SGObject* o, SGScene* s);
00251
00252 protected:
00253
00254 UTRef<PHG2Frame> lhs, rhs;
00255
00256
00257 virtual PHConstraint2D* dup() = 0;
00258
00259 virtual PHG2Result Solve(PHConstraintList2D& newcon) = 0;
00260
00261 PHConstraint2D(){}
00262 PHConstraint2D(PHConstraint2DType _type){
00263 type = _type;
00264
00265
00266 }
00267 virtual ~PHConstraint2D(){}
00268 };
00269
00270
00271 class PHConstraintList2D : public std::list<UTRef<PHConstraint2D> >{
00272 public:
00273 PHConstraintList2D& operator=(const PHConstraintList2D& src){
00274 resize(src.size());
00275 iterator it0;
00276 const_iterator it1;
00277 for(it0 = begin(), it1 = src.begin();
00278 it0 != end();
00279 it0++, it1++){
00280 *it0 = (*it1)->dup();
00281 }
00282 return *this;
00283 }
00284 PHConstraintList2D(){}
00285 PHConstraintList2D(const PHConstraintList2D& src){*this = src;}
00286 };
00287
00288
00289 class PHGeometry2DEngine : public SGBehaviorEngine{
00290 public:
00291 SGOBJECTDEF(PHGeometry2DEngine);
00292
00293
00294 virtual bool AddChildObject(SGObject* o, SGScene* s);
00295 virtual bool DelChildObject(SGObject* o, SGScene* s);
00296 virtual int GetPriority() const {return SGBP_GEOMETRYENGINE;}
00297 virtual void Step(SGScene* s);
00298 virtual void Loaded(SGScene* scene);
00299 virtual void Clear(SGScene* s);
00300 virtual size_t NChildObjects(){ return frames.size(); }
00301 virtual SGObject* ChildObject(size_t i){ return (SGObject*)&*(frames[i]); }
00302
00303
00304
00305 PHConstraint2D* Add(PHConstraint2D* con, SGFrame* lhs, SGFrame* rhs);
00306
00307
00308 void Remove(PHConstraint2D*);
00309
00310
00311
00312
00313
00314
00315
00316 PHGeometry2DEngine(){}
00317 ~PHGeometry2DEngine(){}
00318 protected:
00319 UTRef<PHG2Frame> plane;
00320 PHG2FrameList frames;
00321 PHConstraintList2D cons, cons_tmp;
00322
00323 void _Preprocess();
00324 void _Postprocess();
00325 };
00326
00327
00328
00329
00330
00331 class PHPointToPoint2D : public PHConstraint2D, public PHG2::XPointToPoint2D{
00332 public:
00333 SGOBJECTDEF(PHPointToPoint2D);
00334 PHPointToPoint2D(){}
00335 PHPointToPoint2D(
00336 const Vec2f& _p,
00337 const Vec2f& _q):
00338 PHConstraint2D(PHG2_POINT_TO_POINT)
00339 {point_l = _p; point_r = _q;}
00340 PHConstraint2D* dup(){return new PHPointToPoint2D(lhs->frame, point_l, rhs->frame, point_r);}
00341 PHG2Result Solve(PHConstraintList2D&);
00342 };
00343
00344
00345 class PHPointToLine2D : public PHConstraint2D, public PHG2::XPointToLine2D{
00346 public:
00347 SGOBJECTDEF(PHPointToLine2D);
00348 PHPointToLine2D(){}
00349 PHPointToLine2D(
00350 SGFrame* _lhs, const Vec2f& _p,
00351 SGFrame* _rhs, const Vec2f& _q0, const Vec2f& _q1):
00352 PHConstraint2D(PHG2_POINT_TO_LINE, _lhs, _rhs)
00353 {point = _p; line0 = _q0; line1 = _q1;}
00354 PHConstraint2D* dup(){return new PHPointToLine2D(lhs->frame, point, rhs->frame, line0, line1);}
00355 PHG2Result Solve(PHConstraintList2D&);
00356 };
00357
00358
00359 class PHPointToArc2D : public PHConstraint2D, public PHG2::XPointToArc2D{
00360 public:
00361 SGOBJECTDEF(PHPointToArc2D);
00362 PHPointToArc2D(){}
00363 PHPointToArc2D(
00364 SGFrame* _lhs, const Vec2f& _p,
00365 SGFrame* _rhs, const Vec2f& _c, float _r, float _s0, float _s1):
00366 PHConstraint2D(PHG2_POINT_TO_ARC, _lhs, _rhs)
00367 {point = _p; center = _c; radius = _r; limit0 = _s0; limit1 = _s1;}
00368 PHConstraint2D* dup(){return new PHPointToArc2D(lhs->frame, point, rhs->frame, center, radius, limit0, limit1);}
00369 PHG2Result Solve(PHConstraintList2D&);
00370 };
00371
00372
00373 class PHLineToLine2D : public PHConstraint2D, public PHG2::XLineToLine2D{
00374 public:
00375 SGOBJECTDEF(PHLineToLine2D);
00376 PHLineToLine2D(){}
00377 PHLineToLine2D(
00378 SGFrame* _lhs, const Vec2f& _p0, const Vec2f& _p1,
00379 SGFrame* _rhs, const Vec2f& _q0, const Vec2f& _q1):
00380 PHConstraint2D(PHG2_LINE_TO_LINE, _lhs, _rhs)
00381 {line0_l = _p0; line1_l = _p1; line0_r = _q0; line1_r = _q1;}
00382 PHConstraint2D* dup(){return new PHLineToLine2D(lhs->frame, line0_l, line1_l, rhs->frame, line0_r, line1_r);}
00383 PHG2Result Solve(PHConstraintList2D&);
00384 };
00385
00386
00387 class PHLineToArc2D : public PHConstraint2D, public PHG2::XLineToArc2D{
00388 public:
00389 SGOBJECTDEF(PHLineToArc2D);
00390 PHLineToArc2D(){}
00391 PHLineToArc2D(
00392 SGFrame* _lhs, const Vec2f& _p0, const Vec2f& _p1,
00393 SGFrame* _rhs, const Vec2f& _c, float _r, float _s0, float _s1):
00394 PHConstraint2D(PHG2_LINE_TO_ARC, _lhs, _rhs)
00395 {line0 = _p0; line1 = _p1; center = _c; radius = _r; limit0 = _s0; limit1 = _s1;}
00396 PHConstraint2D* dup(){return new PHLineToArc2D(lhs->frame, line0, line1, rhs->frame, center, radius, limit0, limit1);}
00397 PHG2Result Solve(PHConstraintList2D&);
00398 };
00399
00400
00401 class PHArcToArc2D : public PHConstraint2D, public PHG2::XArcToArc2D{
00402 public:
00403 SGOBJECTDEF(PHArcToArc2D);
00404 PHArcToArc2D(){}
00405 PHArcToArc2D(
00406 SGFrame* _lhs, const Vec2f& _c0, float _r0, float _s00, float _s01,
00407 SGFrame* _rhs, const Vec2f& _c1, float _r1, float _s10, float _s11):
00408 PHConstraint2D(PHG2_ARC_TO_ARC, _lhs, _rhs){
00409 center_l = _c0; radius_l = _r0; limit0_l = _s00; limit1_l = _s01;
00410 center_r = _c1; radius_r = _r1; limit0_r = _s10; limit1_r = _s11;
00411 }
00412 PHConstraint2D* dup(){return new PHArcToArc2D(lhs->frame, center_l, radius_l, limit0_l, limit1_l, rhs->frame, center_r, radius_r, limit0_r, limit1_r);}
00413 PHG2Result Solve(PHConstraintList2D&);
00414 };
00415
00416
00417 class PHParallel2D : public PHConstraint2D, public PHG2::XParallel2D{
00418 public:
00419 SGOBJECTDEF(PHParallel2D);
00420 PHParallel2D(){}
00421 PHParallel2D(
00422 SGFrame* _lhs, float _theta0,
00423 SGFrame* _rhs, float _theta1):
00424 PHConstraint2D(PHG2_PARALLEL, _lhs, _rhs)
00425 {dir_l = _theta0; dir_r = _theta1;}
00426 PHConstraint2D* dup(){return new PHParallel2D(lhs->frame, dir_l, rhs->frame, dir_r);}
00427 PHG2Result Solve(PHConstraintList2D&);
00428 };
00429
00430
00431 class PHAngle2D : public PHConstraint2D, public PHG2::XAngle2D{
00432 public:
00433 SGOBJECTDEF(PHAngle2D);
00434 PHAngle2D(){}
00435 PHAngle2D(
00436 SGFrame* _lhs, float _theta0,
00437 SGFrame* _rhs, float _theta1,
00438 float _phi):
00439 PHConstraint2D(PHG2_ANGLE, _lhs, _rhs)
00440 {offset_l = _theta0; offset_r = _theta1; angle = _phi;}
00441 PHConstraint2D* dup(){return new PHAngle2D(lhs->frame, offset_l, rhs->frame, offset_r, angle);}
00442 PHG2Result Solve(PHConstraintList2D&);
00443 };
00444
00445
00446 class PHFix2D : public PHConstraint2D, public PHG2::XFix2D{
00447 public:
00448 SGOBJECTDEF(PHFix2D);
00449 PHFix2D(){}
00450 PHFix2D(
00451 SGFrame* _lhs,
00452 SGFrame* _rhs, const Vec2d& _p, float _theta):
00453 PHConstraint2D(PHG2_FIX, _lhs, _rhs)
00454 {offset = _p; angle = _theta;}
00455 PHConstraint2D* dup(){return new PHFix2D(lhs->frame, rhs->frame, offset, angle);}
00456 PHG2Result Solve(PHConstraintList2D&);
00457 };
00458
00459
00460
00461
00462
00463 inline void RotationAlong(Vec2d* position, double* angle, const Vec2d& center, double rot){
00464 *angle += rot;
00465 *position = Matrix2d::Rot(rot) * (*position - center) + center;
00466 }
00467
00468
00469 inline void NearestPoint(
00470 Vec2d* y,
00471 const Vec2d& p,
00472 const Vec2d& q, const Vec2d& u)
00473 {
00474 *y = q + PTM::dot(u, p - q) / u.square() * u;
00475 }
00476
00477
00478 inline double Line_Line_Angle(
00479 const Vec2d& u0,
00480 const Vec2d& u1)
00481 {
00482 return atan2(PTM::cross(u0, u1), PTM::dot(u0, u1));
00483 }
00484
00485
00486 inline bool Line_Line_Intersect(
00487 Vec2d* y,
00488 const Vec2d& p0, const Vec2d& u0,
00489 const Vec2d& p1, const Vec2d& u1)
00490 {
00491
00492 Matrix2d A(u0, -u1);
00493 if(fabs(A.det()) < 0.0)return false;
00494 Vec2d s = A.inv() * (-p0 + p1);
00495
00496 *y = p0 + s[0] * u0;
00497 return true;
00498 }
00499
00500
00501
00502 inline bool Line_Circle_Intersect(
00503 Vec2d* y0, Vec2d* y1,
00504 const Vec2d& p, const Vec2d& u,
00505 const Vec2d& c, double r)
00506 {
00507
00508 double A = u.square();
00509 double B = PTM::dot(u, (p - c));
00510 double C = (p - c).square() - r * r;
00511
00512 double det = B * B - A * C;
00513 if(det < 0){
00514
00515 NearestPoint(y0, c, p, u);
00516 Vec2d c_y0 = *y0 - c;
00517 *y1 = c + r / c_y0.norm() * c_y0;
00518 return false;
00519 }
00520
00521 double det_root = sqrt(det);
00522 double s0 = (-B + det_root) / A, s1 = (-B - det_root) / A;
00523 *y0 = p + s0 * u, *y1 = p + s1 * u;
00524 return true;
00525 }
00526
00527
00528
00529 inline bool Circle_Circle_Intersect(
00530 Vec2d* y0, Vec2d* y1,
00531 const Vec2d& c0, double r0,
00532 const Vec2d& c1, double r1)
00533 {
00534
00535 Vec2d d = c1 - c0;
00536 double d_norm = d.norm();
00537
00538
00539 double phi = atan2(d.Y(), d.X());
00540 Matrix2d rot = Matrix2d::Rot(phi);
00541
00542 double det =
00543 ( r0 + r1 + d_norm) *
00544 ( r0 + r1 - d_norm) *
00545 ( r0 - r1 + d_norm) *
00546 (-r0 + r1 + d_norm);
00547 if(det < 0){
00548
00549 *y0 = c0 + r0 / d_norm * d;
00550 *y1 = c1 - r1 / d_norm * d;
00551 return false;
00552 }
00553
00554 double h = sqrt(det) / (2 * d_norm);
00555 double w = sqrt(r0 * r0 - h * h);
00556
00557 *y0 = rot * Vec2d(w, h) + c0;
00558 *y1 = rot * Vec2d(w, -h) + c0;
00559 return true;
00560 }
00561
00562
00563
00564
00565
00566 inline int Circle_Circle_Tangent(
00567 const Vec2d& c0, double r0,
00568 const Vec2d& c1, double r1,
00569 Vec2d* p0, Vec2d* p1, Vec2d* p2, Vec2d* p3,
00570 Vec2d* q0, Vec2d* q1, Vec2d* q2, Vec2d* q3)
00571 {
00572 Vec2d d = c1 - c0;
00573 double d_norm = d.norm();
00574 double phi = atan2(d.Y(), d.X());
00575
00576 if(d_norm < PHG2Epsilon)return 0;
00577
00578 double det1 = (r0 - r1) / d_norm;
00579 double det2 = (r0 + r1) / d_norm;
00580 int nline;
00581 double theta;
00582 double _cos, _sin;
00583
00584
00585 if(fabs(det1) > 1.0 + PHG2Epsilon)
00586 return 0;
00587
00588 if(fabs(det1) > 1.0 - PHG2Epsilon){
00589
00590 *p0 = *q0 = Vec2d(r0 > r1 ? r0 : -r0, 0);
00591 nline = 1;
00592 }
00593
00594 else if(det2 > 1.0 + PHG2Epsilon){
00595 theta = acos(det1);
00596 _cos = cos(theta), _sin = sin(theta);
00597 *p0 = Vec2d(r0 * _cos, r0 * _sin);
00598 *p1 = Vec2d(r0 * _cos, -r0 * _sin);
00599 *q0 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00600 *q1 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00601 nline = 2;
00602 }
00603
00604 else if(det2 < PHG2Epsilon){
00605 *p0 = *q0 = Vec2d(r0, 0);
00606 theta = acos(det1);
00607 _cos = cos(theta), _sin = sin(theta);
00608 *p1 = Vec2d(r0 * _cos, r0 * _sin);
00609 *p2 = Vec2d(r0 * _cos, -r0 * _sin);
00610 *q1 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00611 *q2 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00612 nline = 3;
00613 }
00614
00615 else{
00616 theta = acos(det1);
00617 _cos = cos(theta), _sin = sin(theta);
00618 *p0 = Vec2d(r0 * _cos, r0 * _sin);
00619 *p1 = Vec2d(r0 * _cos, -r0 * _sin);
00620 *q0 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00621 *q1 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00622 theta = acos(det2);
00623 _cos = cos(theta), _sin = sin(theta);
00624 *p2 = Vec2d(r0 * _cos, r0 * _sin);
00625 *p3 = Vec2d(r0 * _cos, -r0 * _sin);
00626 *q2 = *p0 + d_norm * _sin * Vec2d( _sin, _cos);
00627 *q3 = *p1 - d_norm * _sin * Vec2d(-_sin, _cos);
00628 nline = 4;
00629 }
00630
00631 Matrix2d rot = Matrix2d::Rot(phi);
00632 *p0 = c0 + rot * *p0;
00633 *q0 = c0 + rot * *q0;
00634 *p1 = c0 + rot * *p1;
00635 *q1 = c0 + rot * *q1;
00636 *p2 = c0 + rot * *p2;
00637 *q2 = c0 + rot * *q2;
00638 *p3 = c0 + rot * *p3;
00639 *q3 = c0 + rot * *q3;
00640 return nline;
00641 }
00642
00643
00644 inline bool Point_On_LineSegment(
00645 const Vec2d& p,
00646 const Vec2d& q0, const Vec2d& q1)
00647 {
00648 Vec2d u = p - q0, v = p - q1;
00649 return
00650 fabs(PTM::cross(u, v)) < u.norm() * v.norm() * PHG2Epsilon &&
00651 PTM::dot(u, v) < PHG2Epsilon;
00652 }
00653
00654
00655
00656 inline bool Point_On_Arc(
00657 const Vec2d& p,
00658 const Vec2d& c, double r, double s0, double s1)
00659 {
00660 while(s0 < -M_PI)s0 += 2 * M_PI;
00661 while(s0 > M_PI)s0 -= 2 * M_PI;
00662 while(s1 < -M_PI)s1 += 2 * M_PI;
00663 while(s1 > M_PI)s1 -= 2 * M_PI;
00664 if(s1 < s0)s1 += 2 * M_PI;
00665
00666 Vec2d u = p - c;
00667 double s = atan2(u.Y(), u.X());
00668 if(s < s0)s += M_PI;
00669 if(s < s1)return true;
00670 return false;
00671 }
00672
00673 }
00674
00675 #endif