00001 #include "joint.h"
00002
00003 #include "error.h"
00004 #include "defines.h"
00005 #include "geom.h"
00006 #include "varnames.h"
00007
00008 #include <math.h>
00009 #include <string.h>
00010
00019 void NewFreeJoint(unsigned int id,
00020 unsigned int linkID1,Tlink *link1,
00021 unsigned int linkID2,Tlink *link2,
00022 Tjoint *j)
00023 {
00024 unsigned int i,k;
00025
00026 if (linkID1==linkID2)
00027 Error("Setting up a joint on a single link");
00028
00029 j->t=FREE_JOINT;
00030
00031 j->id=id;
00032
00033 j->linkID[0]=linkID1;
00034 j->linkID[1]=linkID2;
00035 j->link[0]=link1;
00036 j->link[1]=link2;
00037
00038 for(i=0;i<6;i++)
00039 {
00040 for(k=0;k<3;k++)
00041 j->points[i][k]=0.0;
00042 }
00043
00044 for(i=0;i<3;i++)
00045 {
00046 for(k=0;k<3;k++)
00047 j->normals[i][k]=0.0;
00048 }
00049
00050 j->hasLimits=FALSE;
00051 j->avoidLimits=FALSE;
00052 j->avoidLimitsWeight=0.0;
00053 NewInterval(-INF,INF,&(j->range));
00054 NewInterval(-INF,INF,&(j->range2));
00055
00056 j->obj3d=NO_UINT;
00057 j->rad=0;
00058 j->length=0;
00059 NewColor(0,0,0,&(j->color));
00060
00061 HTransformIdentity(&(j->trs));
00062 }
00063
00064 void NewFixJoint(unsigned int id,
00065 unsigned int linkID1,Tlink *link1,
00066 unsigned int linkID2,Tlink *link2,
00067 THTransform *t,
00068 Tjoint *j)
00069 {
00070 unsigned int i,k;
00071
00072 if (linkID1==linkID2)
00073 Error("Setting up a joint on a single link");
00074
00075 j->t=FIX_JOINT;
00076
00077 HTransformCopy(&(j->trs),t);
00078
00079 j->id=id;
00080
00081 j->linkID[0]=linkID1;
00082 j->linkID[1]=linkID2;
00083 j->link[0]=link1;
00084 j->link[1]=link2;
00085
00086
00087
00088
00089
00090
00091 j->points[0][0]=HTransformGetElement(0,3,t);
00092 j->points[0][1]=HTransformGetElement(1,3,t);
00093 j->points[0][2]=HTransformGetElement(2,3,t);
00094
00095 for(i=1;i<4;i++)
00096 {
00097 for(k=0;k<3;k++)
00098 j->points[i][k]=0.0;
00099 }
00100
00101 for(i=0;i<2;i++)
00102 {
00103 for(k=0;k<3;k++)
00104 j->normals[i][k]=0.0;
00105 }
00106
00107
00108 j->hasLimits=FALSE;
00109 j->avoidLimits=FALSE;
00110 j->avoidLimitsWeight=0.0;
00111 NewInterval(-INF,INF,&(j->range));
00112 NewInterval(-INF,INF,&(j->range2));
00113
00114 j->obj3d=NO_UINT;
00115 j->rad=0;
00116 j->length=0;
00117 NewColor(0,0,0,&(j->color));
00118 }
00119
00120 void NewRevoluteJoint(unsigned int id,
00121 unsigned int linkID1,Tlink *link1,
00122 unsigned int linkID2,Tlink *link2,
00123 double **points,
00124 boolean hasLimits,Tinterval *range,double **rPoints,
00125 boolean avoidLimits,double avoidLimitsWeight,
00126 Tjoint *j)
00127 {
00128 unsigned int i,k;
00129 double nr;
00130
00131 if (linkID1==linkID2)
00132 Error("Setting up a joint on a single link");
00133
00134 j->t=REV_JOINT;
00135
00136 j->id=id;
00137
00138 j->linkID[0]=linkID1;
00139 j->linkID[1]=linkID2;
00140 j->link[0]=link1;
00141 j->link[1]=link2;
00142
00143 for(i=0;i<4;i++)
00144 {
00145 for(k=0;k<3;k++)
00146 j->points[i][k]=points[i][k];
00147 }
00148
00149
00150 for(i=0;i<2;i++)
00151 {
00152 nr=0.0;
00153 for(k=0;k<3;k++)
00154 {
00155 j->normals[i][k]=points[2*i+1][k]-points[2*i][k];
00156 nr+=(j->normals[i][k]*j->normals[i][k]);
00157 }
00158 nr=sqrt(nr);
00159 for(k=0;k<3;k++)
00160 j->normals[i][k]/=nr;
00161 }
00162
00163 j->hasLimits=hasLimits;
00164
00165 if (j->hasLimits)
00166 {
00167 double c;
00168 double center;
00169 THTransform t,rx,a;
00170 double zero[3]={0,0,0};
00171
00172 for(i=0;i<2;i++)
00173 {
00174
00175 nr=0.0;
00176 for(k=0;k<3;k++)
00177 {
00178 j->vrange[i][k]=rPoints[i][k]-points[2*i][k];
00179 nr+=(j->vrange[i][k]*j->vrange[i][k]);
00180 }
00181 nr=sqrt(nr);
00182 for(k=0;k<3;k++)
00183 j->vrange[i][k]/=nr;
00184
00185
00186 c=0;
00187 for(k=0;k<3;k++)
00188 c+=(j->vrange[i][k]*j->normals[i][k]);
00189
00190 if (fabs(c)>ZERO)
00191 Error("Rotation axes and rotation reference vectors are not orthonormal (Revolute Joint)");
00192 }
00193
00194
00195 CopyInterval(&(j->range),range);
00196
00197
00198 center=IntervalCenter(&(j->range));
00199 IntervalOffset(&(j->range),-center,&(j->range));
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 HTransformX2Vect(1,1,zero,j->normals[0],&t);
00211
00212 HTransformRx(center,&rx);
00213
00214 HTransformInverse(&t,&a);
00215 HTransformProduct(&rx,&a,&a);
00216 HTransformProduct(&t,&a,&a);
00217
00218 HTransformApply(j->vrange[0],j->vrange[0],&a);
00219
00220 HTransformDelete(&a);
00221 HTransformDelete(&rx);
00222 HTransformDelete(&t);
00223
00224 j->avoidLimits=avoidLimits;
00225 j->avoidLimitsWeight=avoidLimitsWeight;
00226 }
00227 else
00228 {
00229
00230 NewInterval(-INF,INF,&(j->range));
00231 for(i=0;i<2;i++)
00232 {
00233 for(k=0;k<3;k++)
00234 j->vrange[i][k]=0.0;
00235 }
00236 j->avoidLimits=FALSE;
00237 j->avoidLimitsWeight=0;
00238 }
00239
00240 NewInterval(-INF,INF,&(j->range2));
00241
00242 j->obj3d=NO_UINT;
00243 j->rad=0;
00244 j->length=0;
00245 NewColor(0,0,0,&(j->color));
00246 HTransformIdentity(&(j->trs));
00247 }
00248
00249
00250 void NewUniversalJoint(unsigned int id,
00251 unsigned int linkID1,Tlink *link1,
00252 unsigned int linkID2,Tlink *link2,
00253 double **points,
00254 boolean hasLimits,
00255 Tinterval*range1,Tinterval *range2,double **rPoints,
00256 boolean avoidLimits,double avoidLimitsWeight,
00257 Tjoint *j)
00258 {
00259 unsigned int i,k;
00260 double nr;
00261
00262 if (linkID1==linkID2)
00263 Error("Setting up a joint on a single link");
00264
00265 j->t=UNV_JOINT;
00266
00267 j->id=id;
00268
00269 j->linkID[0]=linkID1;
00270 j->linkID[1]=linkID2;
00271 j->link[0]=link1;
00272 j->link[1]=link2;
00273
00274 for(i=0;i<4;i++)
00275 {
00276 for(k=0;k<3;k++)
00277 j->points[i][k]=points[i][k];
00278 }
00279
00280
00281 for(i=0;i<2;i++)
00282 {
00283 nr=0.0;
00284 for(k=0;k<3;k++)
00285 {
00286 j->normals[i][k]=points[2*i+1][k]-points[2*i][k];
00287 nr+=(j->normals[i][k]*j->normals[i][k]);
00288 }
00289 nr=sqrt(nr);
00290 for(k=0;k<3;k++)
00291 j->normals[i][k]/=nr;
00292 }
00293
00294 j->hasLimits=hasLimits;
00295
00296 if (j->hasLimits)
00297 {
00298 double c;
00299 double center;
00300 THTransform t,rx,a;
00301 double zero[3]={0,0,0};
00302 Tinterval *rd,*rs;
00303
00304 for(i=0;i<2;i++)
00305 {
00306
00307 nr=0.0;
00308 for(k=0;k<3;k++)
00309 {
00310 j->vrange[i][k]=rPoints[i][k]-points[2*i][k];
00311 nr+=(j->vrange[i][k]*j->vrange[i][k]);
00312 }
00313 nr=sqrt(nr);
00314 for(k=0;k<3;k++)
00315 j->vrange[i][k]/=nr;
00316
00317
00318 c=0;
00319 for(k=0;k<3;k++)
00320 c+=(j->vrange[i][k]*j->normals[i][k]);
00321
00322 if (fabs(c)>ZERO)
00323 Error("Rotation axes and rotation reference vectors are not orthonormal (Universal Joint)");
00324
00325
00326 }
00327
00328
00329
00330 for(k=0;k<3;k++)
00331 {
00332 if (k==0)
00333 {
00334 rs=range1;
00335 rd=&(j->range);
00336 }
00337 else
00338 {
00339 rs=range2;
00340 rd=&(j->range2);
00341 }
00342
00343 CopyInterval(rd,rs);
00344
00345 center=IntervalCenter(rd);
00346 IntervalOffset(rd,-center,rd);
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 HTransformX2Vect(1,1,zero,j->normals[k],&t);
00357
00358 HTransformRx(center,&rx);
00359
00360 HTransformInverse(&t,&a);
00361 HTransformProduct(&rx,&a,&a);
00362 HTransformProduct(&t,&a,&a);
00363
00364 HTransformApply(j->vrange[k],j->vrange[k],&a);
00365
00366 HTransformDelete(&a);
00367 HTransformDelete(&rx);
00368 HTransformDelete(&t);
00369 }
00370 j->avoidLimits=avoidLimits;
00371 j->avoidLimitsWeight=avoidLimitsWeight;
00372 }
00373 else
00374 {
00375
00376 NewInterval(-INF,INF,&(j->range));
00377 NewInterval(-INF,INF,&(j->range2));
00378 for(i=0;i<2;i++)
00379 {
00380 for(k=0;k<3;k++)
00381 j->vrange[i][k]=0.0;
00382 }
00383 j->avoidLimits=FALSE;
00384 j->avoidLimitsWeight=0.0;
00385 }
00386
00387 j->obj3d=NO_UINT;
00388 j->rad=0;
00389 j->length=0;
00390 NewColor(0,0,0,&(j->color));
00391 HTransformIdentity(&(j->trs));
00392 }
00393
00394 void NewSphericalJoint(unsigned int id,
00395 unsigned int linkID1,Tlink *link1,
00396 unsigned int linkID2,Tlink *link2,
00397 double **points,
00398 boolean hasLimits,double range,double **rPoints,
00399 boolean avoidLimits,double avoidLimitsWeight,
00400 Tjoint *j)
00401 {
00402 unsigned int i,k;
00403 double nr;
00404
00405 if (linkID1==linkID2)
00406 Error("Setting up a joint on a single link");
00407
00408 j->t=SPH_JOINT;
00409
00410 j->id=id;
00411
00412 j->linkID[0]=linkID1;
00413 j->linkID[1]=linkID2;
00414 j->link[0]=link1;
00415 j->link[1]=link2;
00416
00417
00418
00419 for(k=0;k<3;k++)
00420 {
00421 j->points[0][k]=points[0][k];
00422 j->points[1][k]=points[0][k];
00423 }
00424 for(k=0;k<3;k++)
00425 {
00426 j->points[2][k]=points[2][k];
00427 j->points[3][k]=points[2][k];
00428 }
00429
00430 j->hasLimits=hasLimits;
00431
00432 if (j->hasLimits)
00433 {
00434 NewInterval(-range,range,&(j->range));
00435
00436 for(i=0;i<2;i++)
00437 {
00438 nr=0.0;
00439 for(k=0;k<3;k++)
00440 {
00441 j->vrange[i][k]=rPoints[i][k]-points[2*i][k];
00442 nr+=(j->vrange[i][k]*j->vrange[i][k]);
00443 }
00444 nr=sqrt(nr);
00445 for(k=0;k<3;k++)
00446 j->vrange[i][k]/=nr;
00447 }
00448 j->avoidLimits=avoidLimits;
00449 j->avoidLimitsWeight=avoidLimitsWeight;
00450 }
00451 else
00452 {
00453
00454 NewInterval(-INF,INF,&(j->range));
00455 for(i=0;i<2;i++)
00456 {
00457 for(k=0;k<3;k++)
00458 j->vrange[i][k]=0.0;
00459 }
00460 j->avoidLimits=FALSE;
00461 j->avoidLimitsWeight=0.0;
00462 }
00463
00464 NewInterval(-INF,INF,&(j->range2));
00465
00466 j->obj3d=NO_UINT;
00467 j->rad=0;
00468 j->length=0;
00469 NewColor(0,0,0,&(j->color));
00470 HTransformIdentity(&(j->trs));
00471 }
00472
00473 void NewPrismaticJoint(unsigned int id,
00474 unsigned int linkID1,Tlink *link1,
00475 unsigned int linkID2,Tlink *link2,
00476 double **points,Tinterval *range,
00477 boolean avoidLimits,double avoidLimitsWeight,
00478 Tjoint *j)
00479 {
00480 unsigned int i,k;
00481 double nr;
00482
00483 if (linkID1==linkID2)
00484 Error("Setting up a joint on a single link");
00485
00486 j->t=PRS_JOINT;
00487
00488 j->id=id;
00489
00490 j->linkID[0]=linkID1;
00491 j->linkID[1]=linkID2;
00492 j->link[0]=link1;
00493 j->link[1]=link2;
00494
00495 for(i=0;i<4;i++)
00496 {
00497 for(k=0;k<3;k++)
00498 j->points[i][k]=points[i][k];
00499 }
00500
00501 for(i=0;i<2;i++)
00502 {
00503 nr=0.0;
00504 for(k=0;k<3;k++)
00505 {
00506 j->normals[i][k]=points[2*i+1][k]-points[2*i][k];
00507 nr+=(j->normals[i][k]*j->normals[i][k]);
00508 }
00509 nr=sqrt(nr);
00510 for(k=0;k<3;k++)
00511 j->normals[i][k]/=nr;
00512 }
00513
00514 j->hasLimits=TRUE;
00515 CopyInterval(&(j->range),range);
00516
00517
00518 for(i=0;i<2;i++)
00519 {
00520 for(k=0;k<3;k++)
00521 j->vrange[i][k]=0.0;
00522 }
00523
00524 NewInterval(-INF,INF,&(j->range2));
00525
00526 j->obj3d=NO_UINT;
00527 j->rad=0;
00528 j->length=0;
00529 NewColor(0,0,0,&(j->color));
00530 HTransformIdentity(&(j->trs));
00531
00532 j->avoidLimits=avoidLimits;
00533 j->avoidLimitsWeight=avoidLimitsWeight;
00534 }
00535
00536 void NewSphSphJoint(unsigned int id,
00537 unsigned int linkID1,Tlink *link1,
00538 unsigned int linkID2,Tlink *link2,
00539 double **points,
00540 double l,double r,
00541 Tcolor *color,
00542 Tjoint *j)
00543 {
00544 unsigned int i,k;
00545
00546 if (linkID1==linkID2)
00547 Error("Setting up a joint on a single link");
00548
00549 j->t=SPH_SPH_JOINT;
00550
00551 j->id=id;
00552
00553 j->linkID[0]=linkID1;
00554 j->linkID[1]=linkID2;
00555 j->link[0]=link1;
00556 j->link[1]=link2;
00557
00558
00559
00560 for(k=0;k<3;k++)
00561 {
00562 j->points[0][k]=points[0][k];
00563 j->points[1][k]=points[0][k];
00564 }
00565 for(k=0;k<3;k++)
00566 {
00567 j->points[2][k]=points[1][k];
00568 j->points[3][k]=points[1][k];
00569 }
00570
00571 j->hasLimits=FALSE;
00572 j->avoidLimits=FALSE;
00573
00574
00575 NewInterval(-INF,INF,&(j->range));
00576 NewInterval(-INF,INF,&(j->range2));
00577 for(i=0;i<2;i++)
00578 {
00579 for(k=0;k<3;k++)
00580 j->vrange[i][k]=0.0;
00581 }
00582
00583 j->obj3d=NO_UINT;
00584 j->rad=r;
00585 j->length=l;
00586 CopyColor(&(j->color),color);
00587 HTransformIdentity(&(j->trs));
00588 }
00589
00590 void NewInPatchJoint(unsigned int id,
00591 unsigned int linkID1,Tlink *link1,
00592 unsigned int linkID2,Tlink *link2,
00593 double **points,
00594 double **patch,
00595 boolean avoidLimits,double avoidLimitsWeight,
00596 Tjoint *j)
00597 {
00598 unsigned int k;
00599 double aux[3],t1[3],t2[3];
00600 double n1,n2;
00601 double p[3][3];
00602 Tinterval tx,ty,tz,a;
00603
00604 if (linkID1==linkID2)
00605 Error("Setting up a joint on a single link");
00606
00607 j->t=IN_PATCH_JOINT;
00608
00609 j->id=id;
00610
00611 j->linkID[0]=linkID1;
00612 j->linkID[1]=linkID2;
00613 j->link[0]=link1;
00614 j->link[1]=link2;
00615
00616
00617 for(k=0;k<3;k++)
00618 {
00619 j->points[0][k]=points[0][k];
00620 j->points[1][k]=points[1][k]-points[0][k];
00621 }
00622
00623
00624
00625
00626 for(k=0;k<3;k++)
00627 {
00628 j->points[2][k]=patch[0][k];
00629 j->points[3][k]=patch[2][k]-patch[0][k];
00630 j->points[4][k]=patch[1][k]-patch[0][k];
00631 j->points[5][k]=patch[0][k]-patch[1][k]-patch[2][k]+patch[3][k];
00632 }
00633
00634
00635 n1=DotProduct(j->points[3],j->points[3]);
00636 n2=DotProduct(j->points[4],j->points[4]);
00637
00638 if ((n1<ZERO)||(n2<ZERO))
00639 Error("Patch is too small");
00640
00641
00642 CrossProduct(j->points[3],j->points[4],j->normals[0]);
00643
00644 CrossProduct(j->points[3],j->points[5],j->normals[1]);
00645
00646 CrossProduct(j->points[5],j->points[4],j->normals[2]);
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 for(k=0;k<3;k++)
00660 aux[k]=patch[3][k]-patch[0][k];
00661
00662 if ((DotProduct(aux,j->points[3])<ZERO)||
00663 (DotProduct(aux,j->points[4])<ZERO))
00664 Error("Patch with overlapping points");
00665
00666 CrossProduct(j->points[3],aux,t1);
00667 CrossProduct(aux,j->points[4],t2);
00668
00669
00670 if (DotProduct(t1,t2)<ZERO)
00671 Error("Patch points given in the wrong order");
00672
00673
00674 for(k=0;k<3;k++)
00675 {
00676 p[k][0]=j->normals[0][k];
00677 p[k][1]=t1[k];
00678 p[k][2]=t2[k];
00679 }
00680
00681 ComputeBoundingBox3d(3,p[0],p[1],p[2],&tx,&ty,&tz);
00682 IntervalPow(&tx,2,&(j->normRange));
00683 IntervalPow(&ty,2,&a);
00684 IntervalAdd(&(j->normRange),&a,&(j->normRange));
00685 IntervalPow(&tz,2,&a);
00686 IntervalAdd(&(j->normRange),&a,&(j->normRange));
00687 IntervalSqrt(&(j->normRange),&(j->normRange));
00688
00689 if (LowerLimit(&(j->normRange))<ZERO)
00690 Error("The lower limit for the norm vector bounds for a IN_PATCH_JOINT should not be zero.");
00691
00692
00693 j->hasLimits=TRUE;
00694 j->avoidLimits=avoidLimits;
00695 j->avoidLimitsWeight=avoidLimitsWeight;
00696 }
00697
00698 void CopyJoint(Tjoint *j_dst,Tjoint *j_src)
00699 {
00700 unsigned int i,k;
00701
00702 j_dst->t=j_src->t;
00703
00704 j_dst->id=j_src->id;
00705
00706 for(i=0;i<2;i++)
00707 {
00708 j_dst->linkID[i]=j_src->linkID[i];
00709 j_dst->link[i]=j_src->link[i];
00710 }
00711
00712 for(i=0;i<6;i++)
00713 {
00714 for(k=0;k<3;k++)
00715 j_dst->points[i][k]=j_src->points[i][k];
00716 }
00717
00718 for(i=0;i<3;i++)
00719 {
00720 for(k=0;k<3;k++)
00721 j_dst->normals[i][k]=j_src->normals[i][k];
00722 }
00723
00724 j_dst->hasLimits=j_src->hasLimits;
00725 j_dst->avoidLimits=j_src->avoidLimits;
00726 j_dst->avoidLimitsWeight=j_src->avoidLimitsWeight;
00727
00728 CopyInterval(&(j_dst->normRange),&(j_src->normRange));
00729
00730 CopyInterval(&(j_dst->range),&(j_src->range));
00731 CopyInterval(&(j_dst->range2),&(j_src->range2));
00732
00733 for(i=0;i<2;i++)
00734 {
00735 for(k=0;k<3;k++)
00736 j_dst->vrange[i][k]=j_src->vrange[i][k];
00737 }
00738
00739 j_dst->obj3d=j_src->obj3d;
00740 j_dst->rad=j_src->rad;
00741 j_dst->length=j_src->length;
00742 CopyColor(&(j_dst->color),&(j_src->color));
00743
00744 HTransformCopy(&(j_dst->trs),&(j_src->trs));
00745 }
00746
00747 unsigned int GetJointType(Tjoint *j)
00748 {
00749 return(j->t);
00750 }
00751
00752 unsigned int GetJointID(Tjoint *j)
00753 {
00754 return(j->id);
00755 }
00756
00757 unsigned int JointFromID(Tjoint *j)
00758 {
00759 return(j->linkID[0]);
00760 }
00761
00762 Tlink *JointFrom(Tjoint *j)
00763 {
00764 return(j->link[0]);
00765 }
00766
00767 unsigned int JointToID(Tjoint *j)
00768 {
00769 return(j->linkID[1]);
00770 }
00771
00772 Tlink *JointTo(Tjoint *j)
00773 {
00774 return(j->link[1]);
00775 }
00776
00777 void GetJointPoint(unsigned int link,unsigned int point,double *p,Tjoint *j)
00778 {
00779 unsigned int i,k;
00780
00781 i=link*2+point;
00782
00783 for(k=0;k<3;k++)
00784 p[k]=j->points[i][k];
00785 }
00786
00787 boolean LimitedJoint(Tjoint *j)
00788 {
00789 return(j->hasLimits);
00790 }
00791
00792 Tinterval *GetJointRange(Tjoint *j)
00793 {
00794 return(&(j->range));
00795 }
00796
00797 Tinterval *GetJointSecondRange(Tjoint *j)
00798 {
00799 return(&(j->range2));
00800 }
00801
00802 signed int GetJointDOF(Tjoint *j)
00803 {
00804 signed int ndof;
00805
00806 switch(j->t)
00807 {
00808 case FREE_JOINT:
00809 ndof=6;
00810 break;
00811 case FIX_JOINT:
00812 ndof=0;
00813 break;
00814 case PRS_JOINT:
00815 ndof=1;
00816 break;
00817 case SPH_JOINT:
00818 ndof=3;
00819 break;
00820 case REV_JOINT:
00821 ndof=1;
00822 break;
00823 case UNV_JOINT:
00824 ndof=2;
00825 break;
00826 case SPH_SPH_JOINT:
00827 ndof=5;
00828 break;
00829 case IN_PATCH_JOINT:
00830 ndof=2;
00831 break;
00832 default:
00833 Error("Undefined joint type in GetJointDOF");
00834 }
00835 return(ndof);
00836 }
00837
00838 double GetJointLength(Tjoint *j)
00839 {
00840 if (j->t!=SPH_SPH_JOINT)
00841 Error("The length is only defined for spherical-spherical composite joints");
00842
00843 return(j->length);
00844 }
00845
00846 THTransform *GetJointTransform(Tjoint *j)
00847 {
00848 if (j->t!=FIX_JOINT)
00849 Error("The transform is only defined for spherical-spherical composite joints");
00850
00851 return(&(j->trs));
00852 }
00853
00854 void GenerateJointRangeEquations(Tparameters *p,TCuikSystem *cs,Tjoint *j)
00855 {
00856
00857
00858 char *vname;
00859 unsigned int i,k,id,nv;
00860 Tequation eq[3],eq1;
00861 Tinterval rangeOne,rangeInf;
00862 Tmonomial f;
00863 unsigned int jointVars[4][3];
00864 Tvariable var;
00865 char *ln1,*ln2;
00866 Tinterval ic;
00867 double r;
00868
00869 NewInterval(-1.0,1.0,&rangeOne);
00870 NewInterval(-INF,INF,&rangeInf);
00871
00872 InitMonomial(&f);
00873
00874 ln1=GetLinkName(j->link[0]);
00875 ln2=GetLinkName(j->link[1]);
00876
00877 NEW(vname,strlen(ln1)+strlen(ln2)+100,char);
00878
00879 switch(j->t)
00880 {
00881 case FREE_JOINT:
00882
00883
00884
00885 for(k=0;k<3;k++)
00886 {
00887 FREE_JOINT_VAR(vname,j->id,j->linkID[0],ln1,j->linkID[1],ln2,k);
00888
00889 NewVariable(SECONDARY_VAR,vname,&var);
00890 SetVariableInterval(&rangeInf,&var);
00891
00892 AddVariable2CS(&var,cs);
00893
00894 DeleteVariable(&var);
00895 }
00896 break;
00897
00898 case FIX_JOINT:
00899 break;
00900
00901 case PRS_JOINT:
00902
00903 PRS_JOINT_VAR(vname,j->id,ln1,ln2);
00904
00905 NewVariable(SYSTEM_VAR,vname,&var);
00906 SetVariableInterval(&(j->range),&var);
00907
00908 nv=AddVariable2CS(&var,cs);
00909
00910 DeleteVariable(&var);
00911
00912 if (j->avoidLimits)
00913 {
00914 r=IntervalSize(&(j->range))/2;
00915 AddTerm2SearchCriterion(j->avoidLimitsWeight/(r*r),nv,
00916 IntervalCenter(&(j->range)),cs);
00917 }
00918
00919 break;
00920
00921 case UNV_JOINT:
00922 case REV_JOINT:
00923 case SPH_JOINT:
00924 if (j->hasLimits)
00925 {
00926
00927
00928 for(k=0;k<2;k++)
00929 {
00930
00931 for(i=0;i<3;i++)
00932 {
00933 InitEquation(&(eq[i]));
00934 SetEquationValue(0.0,&(eq[i]));
00935
00936 if (j->t==REV_JOINT)
00937 ROT_JOINT_VAR_REF(vname,j->id,k,ln1,ln2,i);
00938 else
00939 {
00940 if (j->t==SPH_JOINT)
00941 SPH_JOINT_VAR_REF(vname,j->id,k,ln1,ln2,i);
00942 else
00943 UNV_JOINT_VAR_REF(vname,j->id,k,ln1,ln2,i);
00944 }
00945
00946 NewVariable(SECONDARY_VAR,vname,&var);
00947 SetVariableInterval(&rangeOne,&var);
00948
00949 id=AddVariable2CS(&var,cs);
00950
00951 DeleteVariable(&var);
00952
00953 jointVars[k][i]=id;
00954 AddVariable2Monomial(id,1,&f);
00955 AddMonomial(&f,&(eq[i]));
00956 ResetMonomial(&f);
00957 }
00958
00959 ApplyLinkRot(-1.0,NO_UINT,j->vrange[k],eq,cs,IsGroundLink(j->linkID[k]),j->link[k]);
00960
00961 for(i=0;i<3;i++)
00962 {
00963 SetEquationCmp(EQU,&(eq[i]));
00964 SetEquationType(SYSTEM_EQ,&(eq[i]));
00965
00966 AddEquation2CS(p,&(eq[i]),cs);
00967 DeleteEquation(&(eq[i]));
00968 }
00969 }
00970
00971 if (j->t==UNV_JOINT)
00972 {
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 for(k=2;k<4;k++)
00985 {
00986 for(i=0;i<3;i++)
00987 {
00988 UNV_JOINT_VAR(vname,j->id,ln1,ln2,k-2,i);
00989 jointVars[k][i]=GetCSVariableID(vname,cs);
00990 }
00991 }
00992
00993 for(k=0;k<2;k++)
00994 {
00995 GenerateDotProductEquation(jointVars[3-k][0],jointVars[3-k][1],jointVars[3-k][2],
00996 jointVars[k][0],jointVars[k][1],jointVars[k][2],
00997 NO_UINT,0,&eq1);
00998
00999 COS_VAR_UNI(vname,j->id,ln1,ln2,k);
01000 NewVariable(SECONDARY_VAR,vname,&var);
01001 if (k==0)
01002 IntervalCosinus(&(j->range),&ic);
01003 else
01004 IntervalCosinus(&(j->range2),&ic);
01005 SetVariableInterval(&ic,&var);
01006 DeleteInterval(&ic);
01007 id=AddVariable2CS(&var,cs);
01008 DeleteVariable(&var);
01009
01010 AddVariable2Monomial(id,1,&f);
01011 AddCt2Monomial(-1,&f);
01012 AddMonomial(&f,&eq1);
01013 ResetMonomial(&f);
01014
01015 SetEquationCmp(EQU,&eq1);
01016 SetEquationType(SYSTEM_EQ,&eq1);
01017 AddEquation2CS(p,&eq1,cs);
01018 DeleteEquation(&eq1);
01019
01020 if (j->avoidLimits)
01021 {
01022 r=IntervalSize(&ic);
01023 AddTerm2SearchCriterion(j->avoidLimitsWeight/(r*r),id,1,cs);
01024 }
01025 }
01026 }
01027 else
01028 {
01029 GenerateDotProductEquation(jointVars[0][0],jointVars[0][1],jointVars[0][2],
01030 jointVars[1][0],jointVars[1][1],jointVars[1][2],
01031 NO_UINT,0,&eq1);
01032
01033 COS_VAR(vname,j->id,ln1,ln2);
01034 NewVariable(SECONDARY_VAR,vname,&var);
01035 IntervalCosinus(&(j->range),&ic);
01036 SetVariableInterval(&ic,&var);
01037 DeleteInterval(&ic);
01038 id=AddVariable2CS(&var,cs);
01039 DeleteVariable(&var);
01040
01041 AddVariable2Monomial(id,1,&f);
01042 AddCt2Monomial(-1,&f);
01043 AddMonomial(&f,&eq1);
01044 ResetMonomial(&f);
01045
01046 SetEquationCmp(EQU,&eq1);
01047 SetEquationType(SYSTEM_EQ,&eq1);
01048 AddEquation2CS(p,&eq1,cs);
01049 DeleteEquation(&eq1);
01050
01051 if (j->avoidLimits)
01052 {
01053 r=IntervalSize(&ic);
01054 AddTerm2SearchCriterion(j->avoidLimitsWeight/(r*r),id,1,cs);
01055 }
01056 }
01057
01058 }
01059 break;
01060
01061 case SPH_SPH_JOINT:
01062
01063 break;
01064
01065 case IN_PATCH_JOINT:
01066
01067
01068 if (j->avoidLimits)
01069 {
01070 IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,0);
01071 nv=GetCSVariableID(vname,cs);
01072 AddTerm2SearchCriterion(j->avoidLimitsWeight,nv,0.5,cs);
01073
01074 IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,1);
01075 nv=GetCSVariableID(vname,cs);
01076 AddTerm2SearchCriterion(j->avoidLimitsWeight,nv,0.5,cs);
01077 }
01078 break;
01079 default:
01080 Error("Undefined joint type in GenerateJointRangeEquations");
01081 }
01082
01083 DeleteInterval(&rangeOne);
01084 DeleteInterval(&rangeInf);
01085
01086 free(vname);
01087 DeleteMonomial(&f);
01088 }
01089
01090 void GenerateJointEquationsInBranch(double s,TCuikSystem *cs,Tequation *eq,Tjoint *j)
01091 {
01092
01093 char *l1name,*l2name,*vname;
01094 unsigned int i,vID,d;
01095 Tmonomial f;
01096
01097 l1name=GetLinkName(j->link[0]);
01098 l2name=GetLinkName(j->link[1]);
01099
01100 switch (j->t)
01101 {
01102 case FREE_JOINT:
01103
01104 NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01105 InitMonomial(&f);
01106 for(i=0;i<3;i++)
01107 {
01108 FREE_JOINT_VAR(vname,j->id,j->linkID[0],l1name,j->linkID[1],l2name,i);
01109
01110 vID=GetCSVariableID(vname,cs);
01111 if (vID==NO_UINT)
01112 Error("Undefined FREE_JOINT variable in GenerateTransEquationsFromBranch");
01113
01114 AddVariable2Monomial(vID,1,&f);
01115 AddCt2Monomial(s,&f);
01116 AddMonomial(&f,&(eq[i]));
01117 ResetMonomial(&f);
01118 }
01119 DeleteMonomial(&f);
01120 free(vname);
01121
01122 break;
01123
01124 case FIX_JOINT:
01125
01126
01127
01128 ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01129 break;
01130
01131 case UNV_JOINT:
01132 case REV_JOINT:
01133 case SPH_JOINT:
01134 ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01135 ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01136 break;
01137
01138 case PRS_JOINT:
01139 ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01140
01141 NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01142 PRS_JOINT_VAR(vname,j->id,l1name,l2name);
01143 d=GetCSVariableID(vname,cs);
01144 free(vname);
01145 if (d==NO_UINT)
01146 Error("Undefined PRS_JOINT variable in GenerateTransEquationsFromBranch");
01147
01148 ApplyLinkRot( s,d,j->normals[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01149
01150 ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01151 break;
01152
01153 case SPH_SPH_JOINT:
01154 ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01155
01156 NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01157 InitMonomial(&f);
01158 for(i=0;i<3;i++)
01159 {
01160 SPH_SPH_JOINT_VAR(vname,j->id,l1name,l2name,i);
01161
01162 vID=GetCSVariableID(vname,cs);
01163 if (vID==NO_UINT)
01164 Error("Undefined SPH_SPH_JOINT variable in GenerateTransEquationsFromBranch");
01165
01166 AddVariable2Monomial(vID,1,&f);
01167 AddCt2Monomial(s*j->length,&f);
01168 AddMonomial(&f,&(eq[i]));
01169 ResetMonomial(&f);
01170 }
01171 DeleteMonomial(&f);
01172 free(vname);
01173
01174 ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01175 break;
01176
01177 case IN_PATCH_JOINT:
01178 ApplyLinkRot( s,NO_UINT,j->points[0],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01179 ApplyLinkRot(-s,NO_UINT,j->points[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01180
01181 NEW(vname,strlen(l1name)+strlen(l2name)+100,char);
01182 for(i=0;i<3;i++)
01183 {
01184 IN_PATCH_JOINT_CTRL_VAR(vname,j->id,l1name,l2name,i);
01185 vID=GetCSVariableID(vname,cs);
01186 if (vID==NO_UINT)
01187 Error("Undefined IN_PATCH_JOINT variable in GenerateTransEquationsFromBranch");
01188
01189 ApplyLinkRot(-s,vID,j->points[3+i],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01190 }
01191 free(vname);
01192 break;
01193
01194 default:
01195 Error("Unkownd joint type");
01196 }
01197 }
01198
01199 void GenerateJointEquations(Tparameters *p,double maxCoord,
01200 TCuikSystem *cs,Tjoint *j)
01201 {
01202 double v[3];
01203 unsigned int i,k;
01204 Tequation eq[3],eq1;
01205 char *ln1,*ln2,*vname;
01206 Tinterval rangeOne,rangeInf,rangeZeroOne;
01207 Tmonomial f;
01208 unsigned int vID[3];
01209 unsigned int vIDuni[2][3];
01210 unsigned int l;
01211 Tvariable var;
01212
01213 ln1=GetLinkName(j->link[0]);
01214 ln2=GetLinkName(j->link[1]);
01215
01216 NEW(vname,strlen(ln1)+strlen(ln2)+100,char);
01217
01218 NewInterval(-1,1,&rangeOne);
01219 NewInterval(0,1,&rangeZeroOne);
01220
01221 InitMonomial(&f);
01222
01223 switch(j->t)
01224 {
01225 case FREE_JOINT:
01226 NewInterval(-maxCoord,maxCoord,&rangeInf);
01227 for(i=0;i<3;i++)
01228 {
01229 FREE_JOINT_VAR(vname,j->id,j->linkID[0],ln1,j->linkID[1],ln2,i);
01230
01231 NewVariable(SYSTEM_VAR,vname,&var);
01232 SetVariableInterval(&rangeInf,&var);
01233 AddVariable2CS(&var,cs);
01234
01235 DeleteVariable(&var);
01236 }
01237 break;
01238
01239 case FIX_JOINT:
01240
01241
01242 for(i=0;i<3;i++)
01243 {
01244 for(k=0;k<3;k++)
01245 InitEquation(&(eq[k]));
01246
01247 for(k=0;k<3;k++)
01248 v[k]=HTransformGetElement(k,i,&(j->trs));
01249
01250 ApplyLinkRot(1,NO_UINT,v,eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01251
01252 v[0]=v[1]=v[2]=0;
01253 v[i]=1;
01254
01255 ApplyLinkRot(-1,NO_UINT,v,eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01256
01257 for(k=0;k<3;k++)
01258 {
01259 SetEquationType(SYSTEM_EQ,&(eq[k]));
01260 SetEquationCmp(EQU,&(eq[k]));
01261 AddEquation2CS(p,&(eq[k]),cs);
01262 DeleteEquation(&(eq[k]));
01263 }
01264 }
01265 break;
01266
01267 case PRS_JOINT:
01268
01269
01270 for(k=0;k<3;k++)
01271 InitEquation(&(eq[k]));
01272
01273 for(i=0;i<3;i++)
01274 {
01275 v[0]=v[1]=v[2]=0.0;
01276 v[i]=1.0;
01277
01278 for(k=0;k<3;k++)
01279 InitEquation(&(eq[k]));
01280
01281 for(k=0;k<2;k++)
01282 ApplyLinkRot((k==0?+1.0:-1.0),NO_UINT,v,eq,cs,IsGroundLink(j->linkID[k]),j->link[k]);
01283
01284 for(k=0;k<3;k++)
01285 {
01286 SetEquationType(SYSTEM_EQ,&(eq[k]));
01287 SetEquationCmp(EQU,&(eq[k]));
01288 AddEquation2CS(p,&(eq[k]),cs);
01289 DeleteEquation(&(eq[k]));
01290 }
01291 }
01292 break;
01293
01294 case REV_JOINT:
01295
01296 for(k=0;k<3;k++)
01297 InitEquation(&(eq[k]));
01298
01299 for(k=0;k<2;k++)
01300 ApplyLinkRot((k==0?+1.0:-1.0),NO_UINT,j->normals[k],eq,cs,IsGroundLink(j->linkID[k]),j->link[k]);
01301
01302 for(k=0;k<3;k++)
01303 {
01304 SetEquationType(SYSTEM_EQ,&(eq[k]));
01305 SetEquationCmp(EQU,&(eq[k]));
01306 AddEquation2CS(p,&(eq[k]),cs);
01307 DeleteEquation(&(eq[k]));
01308 }
01309 break;
01310
01311 case UNV_JOINT:
01312
01313 for(i=0;i<2;i++)
01314 {
01315 for(k=0;k<3;k++)
01316 InitEquation(&(eq[k]));
01317
01318 ApplyLinkRot(1,NO_UINT,j->normals[i],eq,cs,IsGroundLink(j->linkID[i]),j->link[i]);
01319
01320 for(k=0;k<3;k++)
01321 {
01322 UNV_JOINT_VAR(vname,j->id,ln1,ln2,i,k);
01323
01324 NewVariable(SECONDARY_VAR,vname,&var);
01325 SetVariableInterval(&rangeOne,&var);
01326
01327 vIDuni[i][k]=AddVariable2CS(&var,cs);
01328
01329 DeleteVariable(&var);
01330
01331 AddCt2Monomial(-1.0,&f);
01332 AddVariable2Monomial(vIDuni[i][k],1,&f);
01333 AddMonomial(&f,&(eq[k]));
01334 ResetMonomial(&f);
01335
01336 SetEquationType(SYSTEM_EQ,&(eq[k]));
01337 SetEquationCmp(EQU,&(eq[k]));
01338 AddEquation2CS(p,&(eq[k]),cs);
01339 DeleteEquation(&(eq[k]));
01340 }
01341
01342 }
01343
01344
01345 GenerateDotProductEquation(vIDuni[0][0],vIDuni[0][1],vIDuni[0][2],
01346 vIDuni[1][0],vIDuni[1][1],vIDuni[1][2],
01347 NO_UINT,0,&eq1);
01348 AddEquation2CS(p,&eq1,cs);
01349 DeleteEquation(&eq1);
01350 break;
01351
01352 case SPH_JOINT:
01353
01354
01355 break;
01356
01357 case SPH_SPH_JOINT:
01358
01359
01360 for(i=0;i<3;i++)
01361 {
01362 SPH_SPH_JOINT_VAR(vname,j->id,ln1,ln2,i);
01363
01364 NewVariable(SYSTEM_VAR,vname,&var);
01365 SetVariableInterval(&rangeOne,&var);
01366
01367 vID[i]=AddVariable2CS(&var,cs);
01368
01369 DeleteVariable(&var);
01370 }
01371 GenerateNormEquation(vID[0],vID[1],vID[2],1.0,&eq1);
01372 AddEquation2CS(p,&eq1,cs);
01373 DeleteEquation(&eq1);
01374
01375 break;
01376
01377 case IN_PATCH_JOINT:
01378 for(i=0;i<3;i++)
01379 {
01380 IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,i);
01381
01382 NewVariable((i<2?SYSTEM_VAR:DUMMY_VAR),vname,&var);
01383 SetVariableInterval(&rangeZeroOne,&var);
01384
01385 vID[i]=AddVariable2CS(&var,cs);
01386
01387 DeleteVariable(&var);
01388 }
01389
01390 GenerateSaddleEquation(vID[0],vID[1],vID[2],&eq1);
01391 AddEquation2CS(p,&eq1,cs);
01392 DeleteEquation(&eq1);
01393
01394 for(k=0;k<3;k++)
01395 InitEquation(&(eq[k]));
01396
01397 IN_PATCH_JOINT_SCALE_VAR(vname,j->id,ln1,ln2);
01398
01399 NewVariable(SYSTEM_VAR,vname,&var);
01400 SetVariableInterval(&(j->normRange),&var);
01401 l=AddVariable2CS(&var,cs);
01402 DeleteVariable(&var);
01403
01404 ApplyLinkRot( 1,l,j->points[1],eq,cs,IsGroundLink(j->linkID[0]),j->link[0]);
01405
01406 ApplyLinkRot(-1,NO_UINT,j->normals[0],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01407 ApplyLinkRot(-1, vID[0],j->normals[1],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01408 ApplyLinkRot(-1, vID[1],j->normals[2],eq,cs,IsGroundLink(j->linkID[1]),j->link[1]);
01409
01410 for(k=0;k<3;k++)
01411 {
01412 SetEquationType(SYSTEM_EQ,&(eq[k]));
01413 SetEquationCmp(EQU,&(eq[k]));
01414 AddEquation2CS(p,&(eq[k]),cs);
01415 DeleteEquation(&(eq[k]));
01416 }
01417
01418 break;
01419
01420 default:
01421 Error("Unknown joint type in GenerateJointEquations");
01422 }
01423
01424 free(vname);
01425 DeleteInterval(&rangeOne);
01426 DeleteMonomial(&f);
01427 }
01428
01429
01430 void RegenerateJointSolution(TCuikSystem *cs,double *sol,Tjoint *j)
01431 {
01432 unsigned int i;
01433 unsigned int vID[3];
01434 char *vname,*ln1,*ln2;
01435
01436 ln1=GetLinkName(j->link[0]);
01437 ln2=GetLinkName(j->link[1]);
01438
01439 NEW(vname,strlen(ln1)+strlen(ln2)+100,char);
01440
01441 switch(j->t)
01442 {
01443 case IN_PATCH_JOINT:
01444 for(i=0;i<3;i++)
01445 {
01446 IN_PATCH_JOINT_CTRL_VAR(vname,j->id,ln1,ln2,i);
01447 vID[i]=GetCSVariableID(vname,cs);
01448 }
01449
01450 sol[vID[2]]=sol[vID[0]]*sol[vID[1]];
01451
01452 break;
01453 }
01454
01455 free(vname);
01456 }
01457
01458 double GetJointMaxCoordinate(Tjoint *j)
01459 {
01460 double mc;
01461
01462 switch(j->t)
01463 {
01464 case SPH_SPH_JOINT:
01465 mc=j->length;
01466 break;
01467 case PRS_JOINT:
01468 {
01469 double l,u;
01470
01471 l=fabs(LowerLimit(&(j->range)));
01472 u=fabs(UpperLimit(&(j->range)));
01473 mc=(l>u?l:u);
01474 }
01475 break;
01476 default:
01477 mc=0.0;
01478 }
01479
01480 return(mc);
01481 }
01482
01483 void PlotJoint(Tplot3d *pt,Tjoint *j)
01484 {
01485 if ((j->t==SPH_SPH_JOINT)&&
01486 (j->rad>0))
01487 {
01488 double zero[3]={0,0,0};
01489 double end[3]={0,0,0};
01490
01491 end[0]=j->length;
01492
01493 j->obj3d=StartNew3dObject(&(j->color),pt);
01494 PlotSphere(j->rad*1.5,0,0,0,pt);
01495 PlotCylinder(j->rad,zero,end,pt);
01496 PlotSphere(j->rad*1.5,end[0],end[1],end[2],pt);
01497 Close3dObject(pt);
01498 }
01499 }
01500
01501 void MoveJoint(Tplot3d *pt,TCuikSystem *cs,double *sol,
01502 double **r,Tjoint *j)
01503 {
01504 if (j->t==SPH_SPH_JOINT)
01505 {
01506 THTransform t;
01507 double p[2][3];
01508 unsigned int k,i;
01509 double d,n;
01510
01511
01512
01513
01514 for(k=0;k<2;k++)
01515 {
01516 GetTransform2Link(cs,sol,IsGroundLink(j->linkID[k]),r[j->linkID[k]],
01517 &t,j->link[k]);
01518
01519 for(i=0;i<3;i++)
01520 HTransformApply(j->points[2*k],p[k],&t);
01521
01522 HTransformDelete(&t);
01523 }
01524
01525
01526 n=0;
01527 for(k=0;k<3;k++)
01528 {
01529 d=p[1][k]-p[0][k];
01530 n+=(d*d);
01531 }
01532 n=sqrt(n);
01533
01534 for(k=0;k<3;k++)
01535 p[1][k]=p[0][k]+(p[1][k]-p[0][k])/n;
01536
01537 HTransformX2Vect(1,1,p[0],p[1],&t);
01538
01539 Move3dObject(j->obj3d,&t,pt);
01540
01541 HTransformDelete(&t);
01542 }
01543 }
01544
01545 void DeleteJoint(Tjoint *j)
01546 {
01547 DeleteInterval(&(j->range));
01548 DeleteInterval(&(j->range2));
01549 HTransformDelete(&(j->trs));
01550 }