|
SUMO - Simulation of Urban MObility
|
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 //degenerate case 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; //psi = [0,2*pi) 00025 00026 params.flag = 0; 00027 00028 L1 = -10; 00029 L2 = -10; 00030 00031 // due to the 0-2*pi discontinuity even for perfect arcs, 00032 // (psi-(t2+t0)/2)~{-pi,0, pi} for cocircular solutions 00033 // if (abs(mod(psi -(t2+t0)/2, pi))<eA) % this condition is not correct 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){ // straight line (still need to check mod 2*pi) 00037 k1 = 0; 00038 k2 = 0; 00039 L1 = L; 00040 L2 = 0; 00041 } 00042 else { // single arc 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 //record the solutions the parameters 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; //truly a biarc 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 // tjoin will be incorrect if k1~0 or k2~0 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 // the other possible biarc 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 // since this solution picks the biarc with the bigger turn 00090 // the curvature solutions can still be close to zero 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 // choose the smaller one 00112 // but due to the epsilon settings (eA and eK) we could still get an incorrect solution 00113 // this could be caught by looking at the signs of Ls. 00114 00115 if ((L1>0 && L2>0) && ((L3<0 || L4<0) || (L1+L2)<(L3+L4))){ 00116 //k1 and k2 are the correct solutions 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 //this should never happen 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;//sign(params.K1); //CCW=+1 00166 params.dir2 = params.K2<0 ? -1 : 1;//sign(params.K2); 00167 } 00168 00169 /* ---------------- BiArc support Functions --------------------- */ 00170 00171 double BiArc::compute_join_theta(double k1, double k2) 00172 { 00173 // compute the theta at which the two arcs meet 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 }