Constraints.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) Konstantinos Poulios      (logari81@gmail.com) 2011     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 #include <cmath>
00024 #include "Constraints.h"
00025 
00026 namespace GCS
00027 {
00028 
00030 // Constraints
00032 
00033 Constraint::Constraint()
00034 : origpvec(0), pvec(0), scale(1.), tag(0)
00035 {
00036 }
00037 
00038 void Constraint::redirectParams(MAP_pD_pD redirectionmap)
00039 {
00040     int i=0;
00041     for (VEC_pD::iterator param=origpvec.begin();
00042          param != origpvec.end(); ++param, i++) {
00043         MAP_pD_pD::const_iterator it = redirectionmap.find(*param);
00044         if (it != redirectionmap.end())
00045             pvec[i] = it->second;
00046     }
00047 }
00048 
00049 void Constraint::revertParams()
00050 {
00051     pvec = origpvec;
00052 }
00053 
00054 ConstraintType Constraint::getTypeId()
00055 {
00056     return None;
00057 }
00058 
00059 void Constraint::rescale(double coef)
00060 {
00061     scale = coef * 1.;
00062 }
00063 
00064 double Constraint::error()
00065 {
00066     return 0.;
00067 }
00068 
00069 double Constraint::grad(double *param)
00070 {
00071     return 0.;
00072 }
00073 
00074 double Constraint::maxStep(MAP_pD_D &dir, double lim)
00075 {
00076     return lim;
00077 }
00078 
00079 // Equal
00080 ConstraintEqual::ConstraintEqual(double *p1, double *p2)
00081 {
00082     pvec.push_back(p1);
00083     pvec.push_back(p2);
00084     origpvec = pvec;
00085     rescale();
00086 }
00087 
00088 ConstraintType ConstraintEqual::getTypeId()
00089 {
00090     return Equal;
00091 }
00092 
00093 void ConstraintEqual::rescale(double coef)
00094 {
00095     scale = coef * 1.;
00096 }
00097 
00098 double ConstraintEqual::error()
00099 {
00100     return scale * (*param1() - *param2());
00101 }
00102 
00103 double ConstraintEqual::grad(double *param)
00104 {
00105     double deriv=0.;
00106     if (param == param1()) deriv += 1;
00107     if (param == param2()) deriv += -1;
00108     return scale * deriv;
00109 }
00110 
00111 // Difference
00112 ConstraintDifference::ConstraintDifference(double *p1, double *p2, double *d)
00113 {
00114     pvec.push_back(p1);
00115     pvec.push_back(p2);
00116     pvec.push_back(d);
00117     origpvec = pvec;
00118     rescale();
00119 }
00120 
00121 ConstraintType ConstraintDifference::getTypeId()
00122 {
00123     return Difference;
00124 }
00125 
00126 void ConstraintDifference::rescale(double coef)
00127 {
00128     scale = coef * 1.;
00129 }
00130 
00131 double ConstraintDifference::error()
00132 {
00133     return scale * (*param2() - *param1() - *difference());
00134 }
00135 
00136 double ConstraintDifference::grad(double *param)
00137 {
00138     double deriv=0.;
00139     if (param == param1()) deriv += -1;
00140     if (param == param2()) deriv += 1;
00141     if (param == difference()) deriv += -1;
00142     return scale * deriv;
00143 }
00144 
00145 // P2PDistance
00146 ConstraintP2PDistance::ConstraintP2PDistance(Point &p1, Point &p2, double *d)
00147 {
00148     pvec.push_back(p1.x);
00149     pvec.push_back(p1.y);
00150     pvec.push_back(p2.x);
00151     pvec.push_back(p2.y);
00152     pvec.push_back(d);
00153     origpvec = pvec;
00154     rescale();
00155 }
00156 
00157 ConstraintType ConstraintP2PDistance::getTypeId()
00158 {
00159     return P2PDistance;
00160 }
00161 
00162 void ConstraintP2PDistance::rescale(double coef)
00163 {
00164     scale = coef * 1.;
00165 }
00166 
00167 double ConstraintP2PDistance::error()
00168 {
00169     double dx = (*p1x() - *p2x());
00170     double dy = (*p1y() - *p2y());
00171     double d = sqrt(dx*dx + dy*dy);
00172     double dist  = *distance();
00173     return scale * (d - dist);
00174 }
00175 
00176 double ConstraintP2PDistance::grad(double *param)
00177 {
00178     double deriv=0.;
00179     if (param == p1x() || param == p1y() ||
00180         param == p2x() || param == p2y()) {
00181         double dx = (*p1x() - *p2x());
00182         double dy = (*p1y() - *p2y());
00183         double d = sqrt(dx*dx + dy*dy);
00184         if (param == p1x()) deriv += dx/d;
00185         if (param == p1y()) deriv += dy/d;
00186         if (param == p2x()) deriv += -dx/d;
00187         if (param == p2y()) deriv += -dy/d;
00188     }
00189     if (param == distance()) deriv += -1.;
00190 
00191     return scale * deriv;
00192 }
00193 
00194 double ConstraintP2PDistance::maxStep(MAP_pD_D &dir, double lim)
00195 {
00196     MAP_pD_D::iterator it;
00197     // distance() >= 0
00198     it = dir.find(distance());
00199     if (it != dir.end()) {
00200         if (it->second < 0.)
00201             lim = std::min(lim, -(*distance()) / it->second);
00202     }
00203     // restrict actual distance change
00204     double ddx=0.,ddy=0.;
00205     it = dir.find(p1x());
00206     if (it != dir.end()) ddx += it->second;
00207     it = dir.find(p1y());
00208     if (it != dir.end()) ddy += it->second;
00209     it = dir.find(p2x());
00210     if (it != dir.end()) ddx -= it->second;
00211     it = dir.find(p2y());
00212     if (it != dir.end()) ddy -= it->second;
00213     double dd = sqrt(ddx*ddx+ddy*ddy);
00214     double dist  = *distance();
00215     if (dd > dist) {
00216         double dx = (*p1x() - *p2x());
00217         double dy = (*p1y() - *p2y());
00218         double d = sqrt(dx*dx + dy*dy);
00219         if (dd > d)
00220             lim = std::min(lim, std::max(d,dist)/dd);
00221     }
00222     return lim;
00223 }
00224 
00225 // P2PAngle
00226 ConstraintP2PAngle::ConstraintP2PAngle(Point &p1, Point &p2, double *a, double da_)
00227 : da(da_)
00228 {
00229     pvec.push_back(p1.x);
00230     pvec.push_back(p1.y);
00231     pvec.push_back(p2.x);
00232     pvec.push_back(p2.y);
00233     pvec.push_back(a);
00234     origpvec = pvec;
00235     rescale();
00236 }
00237 
00238 ConstraintType ConstraintP2PAngle::getTypeId()
00239 {
00240     return P2PAngle;
00241 }
00242 
00243 void ConstraintP2PAngle::rescale(double coef)
00244 {
00245     scale = coef * 1.;
00246 }
00247 
00248 double ConstraintP2PAngle::error()
00249 {
00250     double dx = (*p2x() - *p1x());
00251     double dy = (*p2y() - *p1y());
00252     double a = *angle() + da;
00253     double ca = cos(a);
00254     double sa = sin(a);
00255     double x = dx*ca + dy*sa;
00256     double y = -dx*sa + dy*ca;
00257     return scale * atan2(y,x);
00258 }
00259 
00260 double ConstraintP2PAngle::grad(double *param)
00261 {
00262     double deriv=0.;
00263     if (param == p1x() || param == p1y() ||
00264         param == p2x() || param == p2y()) {
00265         double dx = (*p2x() - *p1x());
00266         double dy = (*p2y() - *p1y());
00267         double a = *angle() + da;
00268         double ca = cos(a);
00269         double sa = sin(a);
00270         double x = dx*ca + dy*sa;
00271         double y = -dx*sa + dy*ca;
00272         double r2 = dx*dx+dy*dy;
00273         dx = -y/r2;
00274         dy = x/r2;
00275         if (param == p1x()) deriv += (-ca*dx + sa*dy);
00276         if (param == p1y()) deriv += (-sa*dx - ca*dy);
00277         if (param == p2x()) deriv += ( ca*dx - sa*dy);
00278         if (param == p2y()) deriv += ( sa*dx + ca*dy);
00279     }
00280     if (param == angle()) deriv += -1;
00281 
00282     return scale * deriv;
00283 }
00284 
00285 double ConstraintP2PAngle::maxStep(MAP_pD_D &dir, double lim)
00286 {
00287     // step(angle()) <= pi/18 = 10°
00288     MAP_pD_D::iterator it = dir.find(angle());
00289     if (it != dir.end()) {
00290         double step = std::abs(it->second);
00291         if (step > M_PI/18.)
00292             lim = std::min(lim, (M_PI/18.) / step);
00293     }
00294     return lim;
00295 }
00296 
00297 // P2LDistance
00298 ConstraintP2LDistance::ConstraintP2LDistance(Point &p, Line &l, double *d)
00299 {
00300     pvec.push_back(p.x);
00301     pvec.push_back(p.y);
00302     pvec.push_back(l.p1.x);
00303     pvec.push_back(l.p1.y);
00304     pvec.push_back(l.p2.x);
00305     pvec.push_back(l.p2.y);
00306     pvec.push_back(d);
00307     origpvec = pvec;
00308     rescale();
00309 }
00310 
00311 ConstraintType ConstraintP2LDistance::getTypeId()
00312 {
00313     return P2LDistance;
00314 }
00315 
00316 void ConstraintP2LDistance::rescale(double coef)
00317 {
00318     scale = coef;
00319 }
00320 
00321 double ConstraintP2LDistance::error()
00322 {
00323     double x0=*p0x(), x1=*p1x(), x2=*p2x();
00324     double y0=*p0y(), y1=*p1y(), y2=*p2y();
00325     double dist = *distance();
00326     double dx = x2-x1;
00327     double dy = y2-y1;
00328     double d = sqrt(dx*dx+dy*dy);
00329     double area = std::abs(-x0*dy+y0*dx+x1*y2-x2*y1); // = x1y2 - x2y1 - x0y2 + x2y0 + x0y1 - x1y0 = 2*(triangle area)
00330     return scale * (area/d - dist);
00331 }
00332 
00333 double ConstraintP2LDistance::grad(double *param)
00334 {
00335     double deriv=0.;
00336     // darea/dx0 = (y1-y2)      darea/dy0 = (x2-x1)
00337     // darea/dx1 = (y2-y0)      darea/dy1 = (x0-x2)
00338     // darea/dx2 = (y0-y1)      darea/dy2 = (x1-x0)
00339     if (param == p0x() || param == p0y() ||
00340         param == p1x() || param == p1y() ||
00341         param == p2x() || param == p2y()) {
00342         double x0=*p0x(), x1=*p1x(), x2=*p2x();
00343         double y0=*p0y(), y1=*p1y(), y2=*p2y();
00344         double dx = x2-x1;
00345         double dy = y2-y1;
00346         double d2 = dx*dx+dy*dy;
00347         double d = sqrt(d2);
00348         double area = -x0*dy+y0*dx+x1*y2-x2*y1;
00349         if (param == p0x()) deriv += (y1-y2) / d;
00350         if (param == p0y()) deriv += (x2-x1) / d ;
00351         if (param == p1x()) deriv += ((y2-y0)*d + (dx/d)*area) / d2;
00352         if (param == p1y()) deriv += ((x0-x2)*d + (dy/d)*area) / d2;
00353         if (param == p2x()) deriv += ((y0-y1)*d - (dx/d)*area) / d2;
00354         if (param == p2y()) deriv += ((x1-x0)*d - (dy/d)*area) / d2;
00355         if (area < 0)
00356             deriv *= -1;
00357     }
00358     if (param == distance()) deriv += -1;
00359 
00360     return scale * deriv;
00361 }
00362 
00363 double ConstraintP2LDistance::maxStep(MAP_pD_D &dir, double lim)
00364 {
00365     MAP_pD_D::iterator it;
00366     // distance() >= 0
00367     it = dir.find(distance());
00368     if (it != dir.end()) {
00369         if (it->second < 0.)
00370             lim = std::min(lim, -(*distance()) / it->second);
00371     }
00372     // restrict actual area change
00373     double darea=0.;
00374     double x0=*p0x(), x1=*p1x(), x2=*p2x();
00375     double y0=*p0y(), y1=*p1y(), y2=*p2y();
00376     it = dir.find(p0x());
00377     if (it != dir.end()) darea += (y1-y2) * it->second;
00378     it = dir.find(p0y());
00379     if (it != dir.end()) darea += (x2-x1) * it->second;
00380     it = dir.find(p1x());
00381     if (it != dir.end()) darea += (y2-y0) * it->second;
00382     it = dir.find(p1y());
00383     if (it != dir.end()) darea += (x0-x2) * it->second;
00384     it = dir.find(p2x());
00385     if (it != dir.end()) darea += (y0-y1) * it->second;
00386     it = dir.find(p2y());
00387     if (it != dir.end()) darea += (x1-x0) * it->second;
00388 
00389     darea = std::abs(darea);
00390     if (darea > 0.) {
00391         double dx = x2-x1;
00392         double dy = y2-y1;
00393         double area = 0.3*(*distance())*sqrt(dx*dx+dy*dy);
00394         if (darea > area) {
00395             area = std::max(area, 0.3*std::abs(-x0*dy+y0*dx+x1*y2-x2*y1));
00396             if (darea > area)
00397                 lim = std::min(lim, area/darea);
00398         }
00399     }
00400     return lim;
00401 }
00402 
00403 // PointOnLine
00404 ConstraintPointOnLine::ConstraintPointOnLine(Point &p, Line &l)
00405 {
00406     pvec.push_back(p.x);
00407     pvec.push_back(p.y);
00408     pvec.push_back(l.p1.x);
00409     pvec.push_back(l.p1.y);
00410     pvec.push_back(l.p2.x);
00411     pvec.push_back(l.p2.y);
00412     origpvec = pvec;
00413     rescale();
00414 }
00415 
00416 ConstraintType ConstraintPointOnLine::getTypeId()
00417 {
00418     return PointOnLine;
00419 }
00420 
00421 void ConstraintPointOnLine::rescale(double coef)
00422 {
00423     scale = coef;
00424 }
00425 
00426 double ConstraintPointOnLine::error()
00427 {
00428     double x0=*p0x(), x1=*p1x(), x2=*p2x();
00429     double y0=*p0y(), y1=*p1y(), y2=*p2y();
00430     double dx = x2-x1;
00431     double dy = y2-y1;
00432     double d = sqrt(dx*dx+dy*dy);
00433     double area = -x0*dy+y0*dx+x1*y2-x2*y1; // = x1y2 - x2y1 - x0y2 + x2y0 + x0y1 - x1y0 = 2*(triangle area)
00434     return scale * area/d;
00435 }
00436 
00437 double ConstraintPointOnLine::grad(double *param)
00438 {
00439     double deriv=0.;
00440     // darea/dx0 = (y1-y2)      darea/dy0 = (x2-x1)
00441     // darea/dx1 = (y2-y0)      darea/dy1 = (x0-x2)
00442     // darea/dx2 = (y0-y1)      darea/dy2 = (x1-x0)
00443     if (param == p0x() || param == p0y() ||
00444         param == p1x() || param == p1y() ||
00445         param == p2x() || param == p2y()) {
00446         double x0=*p0x(), x1=*p1x(), x2=*p2x();
00447         double y0=*p0y(), y1=*p1y(), y2=*p2y();
00448         double dx = x2-x1;
00449         double dy = y2-y1;
00450         double d2 = dx*dx+dy*dy;
00451         double d = sqrt(d2);
00452         double area = -x0*dy+y0*dx+x1*y2-x2*y1;
00453         if (param == p0x()) deriv += (y1-y2) / d;
00454         if (param == p0y()) deriv += (x2-x1) / d ;
00455         if (param == p1x()) deriv += ((y2-y0)*d + (dx/d)*area) / d2;
00456         if (param == p1y()) deriv += ((x0-x2)*d + (dy/d)*area) / d2;
00457         if (param == p2x()) deriv += ((y0-y1)*d - (dx/d)*area) / d2;
00458         if (param == p2y()) deriv += ((x1-x0)*d - (dy/d)*area) / d2;
00459     }
00460     return scale * deriv;
00461 }
00462 
00463 // Parallel
00464 ConstraintParallel::ConstraintParallel(Line &l1, Line &l2)
00465 {
00466     pvec.push_back(l1.p1.x);
00467     pvec.push_back(l1.p1.y);
00468     pvec.push_back(l1.p2.x);
00469     pvec.push_back(l1.p2.y);
00470     pvec.push_back(l2.p1.x);
00471     pvec.push_back(l2.p1.y);
00472     pvec.push_back(l2.p2.x);
00473     pvec.push_back(l2.p2.y);
00474     origpvec = pvec;
00475     rescale();
00476 }
00477 
00478 ConstraintType ConstraintParallel::getTypeId()
00479 {
00480     return Parallel;
00481 }
00482 
00483 void ConstraintParallel::rescale(double coef)
00484 {
00485     double dx1 = (*l1p1x() - *l1p2x());
00486     double dy1 = (*l1p1y() - *l1p2y());
00487     double dx2 = (*l2p1x() - *l2p2x());
00488     double dy2 = (*l2p1y() - *l2p2y());
00489     scale = coef / sqrt((dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
00490 }
00491 
00492 double ConstraintParallel::error()
00493 {
00494     double dx1 = (*l1p1x() - *l1p2x());
00495     double dy1 = (*l1p1y() - *l1p2y());
00496     double dx2 = (*l2p1x() - *l2p2x());
00497     double dy2 = (*l2p1y() - *l2p2y());
00498     return scale * (dx1*dy2 - dy1*dx2);
00499 }
00500 
00501 double ConstraintParallel::grad(double *param)
00502 {
00503     double deriv=0.;
00504     if (param == l1p1x()) deriv += (*l2p1y() - *l2p2y()); // = dy2
00505     if (param == l1p2x()) deriv += -(*l2p1y() - *l2p2y()); // = -dy2
00506     if (param == l1p1y()) deriv += -(*l2p1x() - *l2p2x()); // = -dx2
00507     if (param == l1p2y()) deriv += (*l2p1x() - *l2p2x()); // = dx2
00508 
00509     if (param == l2p1x()) deriv += -(*l1p1y() - *l1p2y()); // = -dy1
00510     if (param == l2p2x()) deriv += (*l1p1y() - *l1p2y()); // = dy1
00511     if (param == l2p1y()) deriv += (*l1p1x() - *l1p2x()); // = dx1
00512     if (param == l2p2y()) deriv += -(*l1p1x() - *l1p2x()); // = -dx1
00513 
00514     return scale * deriv;
00515 }
00516 
00517 // Perpendicular
00518 ConstraintPerpendicular::ConstraintPerpendicular(Line &l1, Line &l2)
00519 {
00520     pvec.push_back(l1.p1.x);
00521     pvec.push_back(l1.p1.y);
00522     pvec.push_back(l1.p2.x);
00523     pvec.push_back(l1.p2.y);
00524     pvec.push_back(l2.p1.x);
00525     pvec.push_back(l2.p1.y);
00526     pvec.push_back(l2.p2.x);
00527     pvec.push_back(l2.p2.y);
00528     origpvec = pvec;
00529     rescale();
00530 }
00531 
00532 ConstraintPerpendicular::ConstraintPerpendicular(Point &l1p1, Point &l1p2,
00533                                                  Point &l2p1, Point &l2p2)
00534 {
00535     pvec.push_back(l1p1.x);
00536     pvec.push_back(l1p1.y);
00537     pvec.push_back(l1p2.x);
00538     pvec.push_back(l1p2.y);
00539     pvec.push_back(l2p1.x);
00540     pvec.push_back(l2p1.y);
00541     pvec.push_back(l2p2.x);
00542     pvec.push_back(l2p2.y);
00543     origpvec = pvec;
00544     rescale();
00545 }
00546 
00547 ConstraintType ConstraintPerpendicular::getTypeId()
00548 {
00549     return Perpendicular;
00550 }
00551 
00552 void ConstraintPerpendicular::rescale(double coef)
00553 {
00554     double dx1 = (*l1p1x() - *l1p2x());
00555     double dy1 = (*l1p1y() - *l1p2y());
00556     double dx2 = (*l2p1x() - *l2p2x());
00557     double dy2 = (*l2p1y() - *l2p2y());
00558     scale = coef / sqrt((dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
00559 }
00560 
00561 double ConstraintPerpendicular::error()
00562 {
00563     double dx1 = (*l1p1x() - *l1p2x());
00564     double dy1 = (*l1p1y() - *l1p2y());
00565     double dx2 = (*l2p1x() - *l2p2x());
00566     double dy2 = (*l2p1y() - *l2p2y());
00567     return scale * (dx1*dx2 + dy1*dy2);
00568 }
00569 
00570 double ConstraintPerpendicular::grad(double *param)
00571 {
00572     double deriv=0.;
00573     if (param == l1p1x()) deriv += (*l2p1x() - *l2p2x()); // = dx2
00574     if (param == l1p2x()) deriv += -(*l2p1x() - *l2p2x()); // = -dx2
00575     if (param == l1p1y()) deriv += (*l2p1y() - *l2p2y()); // = dy2
00576     if (param == l1p2y()) deriv += -(*l2p1y() - *l2p2y()); // = -dy2
00577 
00578     if (param == l2p1x()) deriv += (*l1p1x() - *l1p2x()); // = dx1
00579     if (param == l2p2x()) deriv += -(*l1p1x() - *l1p2x()); // = -dx1
00580     if (param == l2p1y()) deriv += (*l1p1y() - *l1p2y()); // = dy1
00581     if (param == l2p2y()) deriv += -(*l1p1y() - *l1p2y()); // = -dy1
00582 
00583     return scale * deriv;
00584 }
00585 
00586 // L2LAngle
00587 ConstraintL2LAngle::ConstraintL2LAngle(Line &l1, Line &l2, double *a)
00588 {
00589     pvec.push_back(l1.p1.x);
00590     pvec.push_back(l1.p1.y);
00591     pvec.push_back(l1.p2.x);
00592     pvec.push_back(l1.p2.y);
00593     pvec.push_back(l2.p1.x);
00594     pvec.push_back(l2.p1.y);
00595     pvec.push_back(l2.p2.x);
00596     pvec.push_back(l2.p2.y);
00597     pvec.push_back(a);
00598     origpvec = pvec;
00599     rescale();
00600 }
00601 
00602 ConstraintL2LAngle::ConstraintL2LAngle(Point &l1p1, Point &l1p2,
00603                                        Point &l2p1, Point &l2p2, double *a)
00604 {
00605     pvec.push_back(l1p1.x);
00606     pvec.push_back(l1p1.y);
00607     pvec.push_back(l1p2.x);
00608     pvec.push_back(l1p2.y);
00609     pvec.push_back(l2p1.x);
00610     pvec.push_back(l2p1.y);
00611     pvec.push_back(l2p2.x);
00612     pvec.push_back(l2p2.y);
00613     pvec.push_back(a);
00614     origpvec = pvec;
00615     rescale();
00616 }
00617 
00618 ConstraintType ConstraintL2LAngle::getTypeId()
00619 {
00620     return L2LAngle;
00621 }
00622 
00623 void ConstraintL2LAngle::rescale(double coef)
00624 {
00625     scale = coef * 1.;
00626 }
00627 
00628 double ConstraintL2LAngle::error()
00629 {
00630     double dx1 = (*l1p2x() - *l1p1x());
00631     double dy1 = (*l1p2y() - *l1p1y());
00632     double dx2 = (*l2p2x() - *l2p1x());
00633     double dy2 = (*l2p2y() - *l2p1y());
00634     double a = atan2(dy1,dx1) + *angle();
00635     double ca = cos(a);
00636     double sa = sin(a);
00637     double x2 = dx2*ca + dy2*sa;
00638     double y2 = -dx2*sa + dy2*ca;
00639     return scale * atan2(y2,x2);
00640 }
00641 
00642 double ConstraintL2LAngle::grad(double *param)
00643 {
00644     double deriv=0.;
00645     if (param == l1p1x() || param == l1p1y() ||
00646         param == l1p2x() || param == l1p2y()) {
00647         double dx1 = (*l1p2x() - *l1p1x());
00648         double dy1 = (*l1p2y() - *l1p1y());
00649         double r2 = dx1*dx1+dy1*dy1;
00650         if (param == l1p1x()) deriv += -dy1/r2;
00651         if (param == l1p1y()) deriv += dx1/r2;
00652         if (param == l1p2x()) deriv += dy1/r2;
00653         if (param == l1p2y()) deriv += -dx1/r2;
00654     }
00655     if (param == l2p1x() || param == l2p1y() ||
00656         param == l2p2x() || param == l2p2y()) {
00657         double dx1 = (*l1p2x() - *l1p1x());
00658         double dy1 = (*l1p2y() - *l1p1y());
00659         double dx2 = (*l2p2x() - *l2p1x());
00660         double dy2 = (*l2p2y() - *l2p1y());
00661         double a = atan2(dy1,dx1) + *angle();
00662         double ca = cos(a);
00663         double sa = sin(a);
00664         double x2 = dx2*ca + dy2*sa;
00665         double y2 = -dx2*sa + dy2*ca;
00666         double r2 = dx2*dx2+dy2*dy2;
00667         dx2 = -y2/r2;
00668         dy2 = x2/r2;
00669         if (param == l2p1x()) deriv += (-ca*dx2 + sa*dy2);
00670         if (param == l2p1y()) deriv += (-sa*dx2 - ca*dy2);
00671         if (param == l2p2x()) deriv += ( ca*dx2 - sa*dy2);
00672         if (param == l2p2y()) deriv += ( sa*dx2 + ca*dy2);
00673     }
00674     if (param == angle()) deriv += -1;
00675 
00676     return scale * deriv;
00677 }
00678 
00679 double ConstraintL2LAngle::maxStep(MAP_pD_D &dir, double lim)
00680 {
00681     // step(angle()) <= pi/18 = 10°
00682     MAP_pD_D::iterator it = dir.find(angle());
00683     if (it != dir.end()) {
00684         double step = std::abs(it->second);
00685         if (step > M_PI/18.)
00686             lim = std::min(lim, (M_PI/18.) / step);
00687     }
00688     return lim;
00689 }
00690 
00691 // MidpointOnLine
00692 ConstraintMidpointOnLine::ConstraintMidpointOnLine(Line &l1, Line &l2)
00693 {
00694     pvec.push_back(l1.p1.x);
00695     pvec.push_back(l1.p1.y);
00696     pvec.push_back(l1.p2.x);
00697     pvec.push_back(l1.p2.y);
00698     pvec.push_back(l2.p1.x);
00699     pvec.push_back(l2.p1.y);
00700     pvec.push_back(l2.p2.x);
00701     pvec.push_back(l2.p2.y);
00702     origpvec = pvec;
00703     rescale();
00704 }
00705 
00706 ConstraintMidpointOnLine::ConstraintMidpointOnLine(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2)
00707 {
00708     pvec.push_back(l1p1.x);
00709     pvec.push_back(l1p1.y);
00710     pvec.push_back(l1p2.x);
00711     pvec.push_back(l1p2.y);
00712     pvec.push_back(l2p1.x);
00713     pvec.push_back(l2p1.y);
00714     pvec.push_back(l2p2.x);
00715     pvec.push_back(l2p2.y);
00716     origpvec = pvec;
00717     rescale();
00718 }
00719 
00720 ConstraintType ConstraintMidpointOnLine::getTypeId()
00721 {
00722     return MidpointOnLine;
00723 }
00724 
00725 void ConstraintMidpointOnLine::rescale(double coef)
00726 {
00727     scale = coef * 1;
00728 }
00729 
00730 double ConstraintMidpointOnLine::error()
00731 {
00732     double x0=((*l1p1x())+(*l1p2x()))/2;
00733     double y0=((*l1p1y())+(*l1p2y()))/2;
00734     double x1=*l2p1x(), x2=*l2p2x();
00735     double y1=*l2p1y(), y2=*l2p2y();
00736     double dx = x2-x1;
00737     double dy = y2-y1;
00738     double d = sqrt(dx*dx+dy*dy);
00739     double area = -x0*dy+y0*dx+x1*y2-x2*y1; // = x1y2 - x2y1 - x0y2 + x2y0 + x0y1 - x1y0 = 2*(triangle area)
00740     return scale * area/d;
00741 }
00742 
00743 double ConstraintMidpointOnLine::grad(double *param)
00744 {
00745     double deriv=0.;
00746     // darea/dx0 = (y1-y2)      darea/dy0 = (x2-x1)
00747     // darea/dx1 = (y2-y0)      darea/dy1 = (x0-x2)
00748     // darea/dx2 = (y0-y1)      darea/dy2 = (x1-x0)
00749     if (param == l1p1x() || param == l1p1y() ||
00750         param == l1p2x() || param == l1p2y()||
00751         param == l2p1x() || param == l2p1y() ||
00752         param == l2p2x() || param == l2p2y()) {
00753         double x0=((*l1p1x())+(*l1p2x()))/2;
00754         double y0=((*l1p1y())+(*l1p2y()))/2;
00755         double x1=*l2p1x(), x2=*l2p2x();
00756         double y1=*l2p1y(), y2=*l2p2y();
00757         double dx = x2-x1;
00758         double dy = y2-y1;
00759         double d2 = dx*dx+dy*dy;
00760         double d = sqrt(d2);
00761         double area = -x0*dy+y0*dx+x1*y2-x2*y1;
00762         if (param == l1p1x()) deriv += (y1-y2) / (2*d);
00763         if (param == l1p1y()) deriv += (x2-x1) / (2*d);
00764         if (param == l1p2x()) deriv += (y1-y2) / (2*d);
00765         if (param == l1p2y()) deriv += (x2-x1) / (2*d);
00766         if (param == l2p1x()) deriv += ((y2-y0)*d + (dx/d)*area) / d2;
00767         if (param == l2p1y()) deriv += ((x0-x2)*d + (dy/d)*area) / d2;
00768         if (param == l2p2x()) deriv += ((y0-y1)*d - (dx/d)*area) / d2;
00769         if (param == l2p2y()) deriv += ((x1-x0)*d - (dy/d)*area) / d2;
00770     }
00771     return scale * deriv;
00772 }
00773 
00774 } //namespace GCS

Generated on Wed Nov 23 19:00:04 2011 for FreeCAD by  doxygen 1.6.1