BiArc.cpp
Go to the documentation of this file.00001 #include "BiArc.h"
00002 #include <cassert>
00003
00004 void BiArc::compute_biarc_params(void)
00005 {
00006 double k1, k2, k3, k4;
00007 double L1, L2, L3, L4;
00008
00009 double t0 = params.start_angle;
00010 double t2 = params.end_angle;
00011 double tjoin;
00012
00013 double L = euc_distance(params.start_pt, params.end_pt);
00014
00015
00016 if (L<eA){
00017 params.K1 = HUGE;
00018 params.K2 = HUGE;
00019 params.E = HUGE;
00020 return;
00021 }
00022
00023 double psi = atan2(params.end_pt.y()-params.start_pt.y(),params.end_pt.x()-params.start_pt.x());
00024 if (psi<0) psi+=2*M_PI;
00025
00026 params.flag = 0;
00027
00028 L1 = -10;
00029 L2 = -10;
00030
00031
00032
00033
00034
00035 if (fabs(psi-(t2+t0)/2)<eA || fabs(psi-(t2+t0)/2+M_PI)<eA || fabs(psi-(t2+t0)/2-M_PI)<eA){
00036 if (fabs(fmod(psi-t0,2*M_PI))<eA){
00037 k1 = 0;
00038 k2 = 0;
00039 L1 = L;
00040 L2 = 0;
00041 }
00042 else {
00043 k1 = -4*sin((3*t0+t2)/4 - psi)*cos((t2-t0)/4)/L;
00044 k2 = 0;
00045 L1 = compute_arclength(t0,t2,k1);
00046 L2 = 0;
00047 }
00048
00049 params.L1 = L1;
00050 params.L2 = L2;
00051 params.K1 = k1;
00052 params.K2 = k2;
00053 params.E = 0;
00054 compute_other_stuff();
00055 return;
00056 }
00057 else {
00058 params.flag = 1;
00059
00060 k1 = -4*sin((3*t0+t2)/4 - psi)*cos((t2-t0)/4)/L;
00061 k2 = 4*sin((t0+3*t2)/4 - psi)*cos((t2-t0)/4)/L;
00062
00063 if (fabs(k1)<eK){
00064 k1 = 0;
00065 L1 = L*sin((t2+t0)/2-psi)/sin((t2-t0)/2);
00066 L2 = compute_arclength(t0,t2,k2);
00067 }
00068 else {
00069 if (fabs(k2)<eK){
00070 k2 = 0;
00071 L2 = L*sin((t2+t0)/2-psi)/sin((t0-t2)/2);
00072 L1 = compute_arclength(t0,t2,k1);
00073 }
00074 else {
00075
00076 tjoin = compute_join_theta(k1,k2);
00077 L1 = compute_arclength(t0,tjoin,k1);
00078 L2 = compute_arclength(tjoin,t2,k2);
00079 }
00080 }
00081
00082
00083 L3 = -10;
00084 L4 = -10;
00085
00086 k3 = 4*cos((3*t0+t2)/4 - psi)*sin((t2-t0)/4)/L;
00087 k4 = 4*cos((t0+3*t2)/4 - psi)*sin((t2-t0)/4)/L;
00088
00089
00090
00091 if ( (fabs(k3)>eK || fabs(k4)>eK) && fabs(k4-k3)>eK){
00092 if (fabs(k3)<eK){
00093 k3 = 0;
00094 L3 = L*sin((t2+t0)/2-psi)/sin((t2-t0)/2);
00095 L4 = compute_arclength(t0,t2,k4);
00096 }
00097 else {
00098 if (fabs(k4)<eK){
00099 k4 = 0;
00100 L4 = L*sin((t2+t0)/2-psi)/sin((t0-t2)/2);
00101 L3 = compute_arclength(t0,t2,k3);
00102 }
00103 else {
00104 tjoin = compute_join_theta(k3,k4);
00105 L3 = compute_arclength(t0,tjoin,k3);
00106 L4 = compute_arclength(tjoin,t2,k4);
00107 }
00108 }
00109 }
00110
00111
00112
00113
00114
00115 if ((L1>0 && L2>0) && ((L3<0 || L4<0) || (L1+L2)<(L3+L4))){
00116
00117 params.L1 = L1;
00118 params.L2 = L2;
00119 params.K1 = k1;
00120 params.K2 = k2;
00121 params.E = (k2-k1)*(k2-k1);
00122 }
00123 else {
00124 if (L3>0 && L4>0){
00125 params.L1 = L3;
00126 params.L2 = L4;
00127 params.K1 = k3;
00128 params.K2 = k4;
00129 params.E = (k3-k4)*(k3-k4);
00130 }
00131 else {
00132
00133 assert(false);
00134 }
00135 }
00136 }
00137 compute_other_stuff();
00138 }
00139
00140 void BiArc::compute_other_stuff(void)
00141 {
00142 if (params.K1 != 0){
00143 params.R1 = fabs(1/params.K1);
00144 params.center1.setX(params.start_pt.x() - cos(params.start_angle-M_PI/2)/params.K1);
00145 params.center1.setY(params.start_pt.y() - sin(params.start_angle-M_PI/2)/params.K1);
00146 double dt = params.L1*params.K1;
00147 params.mid_pt.setX(params.center1.x() - cos(params.start_angle+M_PI/2+dt)/params.K1);
00148 params.mid_pt.setY(params.center1.y() - sin(params.start_angle+M_PI/2+dt)/params.K1);
00149 }
00150 else {
00151 params.mid_pt.setX(params.start_pt.x() + cos(params.start_angle)*params.L1);
00152 params.mid_pt.setY(params.start_pt.y() + sin(params.start_angle)*params.L1);
00153 params.R1 = HUGE;
00154 }
00155
00156 if (params.K2 != 0){
00157 params.R2 = fabs(1/params.K2);
00158 params.center2.setX(params.end_pt.x() - cos(params.end_angle-M_PI/2)/params.K2);
00159 params.center2.setY(params.end_pt.y() - sin(params.end_angle-M_PI/2)/params.K2);
00160 }
00161 else {
00162 params.R2 = HUGE;
00163 }
00164
00165 params.dir1 = params.K1<0 ? -1. : 1.;
00166 params.dir2 = params.K2<0 ? -1. : 1.;
00167 }
00168
00169
00170
00171 double BiArc::compute_join_theta(double k1, double k2)
00172 {
00173
00174 double x0=params.start_pt.x();
00175 double y0=params.start_pt.y();
00176 double x2=params.end_pt.x();
00177 double y2=params.end_pt.y();
00178 double t0=params.start_angle;
00179 double t2=params.end_angle;
00180
00181 double sin_join_theta = (k1*k2*(x2-x0)+k2*sin(t0)-k1*sin(t2))/(k2-k1);
00182 double cos_join_theta = (-k1*k2*(y2-y0)+k2*cos(t0)-k1*cos(t2))/(k2-k1);
00183
00184 double join_theta = atan2(sin_join_theta, cos_join_theta);
00185 if (join_theta<0) join_theta += 2*M_PI;
00186
00187 return join_theta;
00188 }
00189
00190 double BiArc::compute_arclength(double t0, double t1, double k)
00191 {
00192 double num = (t1-t0);
00193
00194 if (k<0 && (t1-t0)>0)
00195 num = num-2*M_PI;
00196 else if (k>0 && (t1-t0)<0)
00197 num = num+2*M_PI;
00198
00199 return num/k;
00200 }