00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <math.h>
00029 #include <windows.h>
00030
00031 #include "struct.h"
00032 #include "dstruct.h"
00033
00034
00035 #include "ik3d.h"
00036
00037 #define VECCOPY(a,b) { b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; }
00038 #define VECSUB(a,b,c) { c[0]=a[0]-b[0]; c[1]=a[1]-b[1]; c[2]=a[2]-b[2];}
00039 #define VECSUM(a,b,c) { c[0]=a[0]+b[0]; c[1]=a[1]+b[1]; c[2]=a[2]+b[2];}
00040 #define VECSCALE(a,b,c) { c[0]=(a)*b[0]; c[1]=(a)*b[1]; c[2]=(a)*b[2];}
00041 #define DOT(a,b) ( (a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2]) )
00042 #define CROSS(v1,v2,r) { \
00043 r[0] = (v1[1]*v2[2]) - (v2[1]*v1[2]); \
00044 r[1] = (v1[2]*v2[0]) - (v1[0]*v2[2]); \
00045 r[2] = (v1[0]*v2[1]) - (v2[0]*v1[1]); \
00046 }
00047
00048 #ifndef PI
00049 #define PI 3.1415926
00050 #endif
00051
00052 #ifndef PI2
00053 #define PI2 PI/2
00054 #endif
00055
00056 static HWND hParent;
00057 static HINSTANCE hThisInstance;
00058 static char *szViewClass="OFX:IKtestClass";
00059 static SYSTEM_INFO sys_info;
00060 static int xScreen,yScreen;
00061 static DWORD fdwStyle = WS_POPUP | WS_CAPTION | ! WS_SYSMENU |
00062 WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
00063 static HCURSOR hcurSave,hcurPen1=NULL;
00064 static char filename[256];
00065
00066 static int pen=0,tracetool=0,version=0;
00067 static long Lv= -1,Fv= -1,Nv=0,Ne=0;
00068 static struct TVLIST {BOOL inc; int x,y,z; long id;
00069 vector p;
00070 vector ax,ay,az;} *TVlist=NULL;
00071 static struct TELIST {BOOL inc; int v1,v2;} *TElist=NULL;
00072 static FILE *debug=NULL;
00073
00074 static LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
00075 static BOOL MenuCommand(HWND, WORD);
00076 static BOOL Tester(void);
00077 static void DrawRubberLine(HWND, int, int);
00078 static void DrawList(HWND, HDC);
00079 static void AddTraceVertex(int, int);
00080 static int GetVertexAtCursor(int, int);
00081 static void IterateTowardsGoal(HWND, int, int);
00082 static void SetupStart(void);
00083 static void RotateVectorRound(vector, vector, vector, double);
00084 static BOOL normalize(vector v);
00085 static void rotz(double [4][4], double);
00086 static void roty(double [4][4], double);
00087 static void rotx(double [4][4], double);
00088 static void mv4by1(double [4][4], vector, vector);
00089 static void m4by4(double [4][4], double [4][4], double [4][4]);
00090 static void rotate_round_vector(double, vector, double [4][4]);
00091 static void CalculateTranspose(double *, double *, long, long);
00092 static void MultiplyMatrix(double *, long, long,
00093 double *, long, long,
00094 double *);
00095 static BOOL InvertMatrix(double *, long, double *);
00096 static BOOL StepOK(double *, double *, double *, long, long, double, double);
00097 static void UpdateTheLinkage(long, double *);
00098 static void CalculateJacobian(double *, long);
00099 static double Length(double *, long);
00100 static double Dist(double *, double *, long);
00101
00102 static BOOL Tester(void){
00103 MSG msg;
00104 HWND hDesktopWnd,hWnd;
00105 HDC hDCcaps;
00106 WNDCLASS wndclass;
00107 TVlist=NULL; TElist=NULL; Nv=0; Ne=0;
00108 hDesktopWnd = GetDesktopWindow();
00109 hDCcaps = GetDC(hDesktopWnd);
00110 ReleaseDC(hDesktopWnd,hDCcaps);
00111 GetSystemInfo(&sys_info);
00112 wndclass.style = 0;
00113 wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
00114 wndclass.cbClsExtra = 0 ;
00115 wndclass.cbWndExtra = 0 ;
00116 wndclass.hInstance = hThisInstance ;
00117 wndclass.hIcon = NULL;
00118 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
00119 wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
00120 wndclass.lpszMenuName = "tracemenu" ;
00121 wndclass.lpszClassName = szViewClass;
00122 if (!RegisterClass (&wndclass)) return FALSE ;
00123 xScreen = GetSystemMetrics(SM_CXSCREEN) ;
00124 yScreen = GetSystemMetrics(SM_CYSCREEN) ;
00125 hWnd = CreateWindow(
00126 szViewClass,
00127 "Pseudo 3D Inverse Kinematics (IK) Test Engine",
00128 fdwStyle,
00129 25,
00130 25,
00131 xScreen-50,
00132 yScreen-50,
00133 hParent,
00134 NULL,
00135 hThisInstance,
00136 NULL) ;
00137 if(hWnd == NULL)return FALSE;
00138 hcurPen1=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PEN1));
00139 ShowWindow (hWnd,SW_SHOWNA);
00140 PostMessage(hWnd,WM_COMMAND,(WPARAM)IDM_DRAWIT,0);
00141 while(GetMessage (&msg,NULL,0,0)){
00142 TranslateMessage (&msg);
00143 DispatchMessage (&msg);
00144 }
00145 DestroyWindow(hWnd);
00146 if(hcurPen1 != NULL)DeleteObject(hcurPen1);
00147 UnregisterClass(wndclass.lpszClassName,wndclass.hInstance);
00148 if(TVlist != NULL)X__Free(TVlist); TVlist=NULL; Nv=0;
00149 if(TElist != NULL)X__Free(TElist); TElist=NULL; Ne=0;
00150 return TRUE;
00151 }
00152
00153 LRESULT CALLBACK MainWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,
00154 LPARAM lParam){
00155 static BOOL bToolCaptured=FALSE;
00156 static HCURSOR hCursorSave;
00157 static POINT LastPt;
00158 PAINTSTRUCT ps;
00159 HDC hDC;
00160 int i;
00161 RECT rc;
00162 POINT pt;
00163 switch (iMessage) {
00164 case WM_DESTROY:
00165 break;
00166 case WM_COMMAND:
00167 return MenuCommand(hWnd,LOWORD(wParam));
00168 break;
00169 case WM_RBUTTONUP:
00170 if(!bToolCaptured)break;
00171 if(tracetool == 1){
00172 DrawRubberLine(hWnd,LOWORD(lParam),HIWORD(lParam));
00173 SetCursor(hCursorSave);
00174 ClipCursor(NULL);
00175 ReleaseCapture();
00176 bToolCaptured=FALSE;
00177 Lv= -1;
00178 }
00179 break;
00180 case WM_LBUTTONDOWN:
00181 if(bToolCaptured)break;
00182 if(tracetool == 1){
00183 bToolCaptured=TRUE;
00184 SetCapture(hWnd);
00185 hCursorSave=SetCursor(hcurPen1);
00186 GetClientRect(hWnd,&rc);
00187 pt.x=rc.left; pt.y=rc.top;
00188 ClientToScreen(hWnd,&pt);
00189 rc.left=pt.x; rc.top=pt.y;
00190 pt.x=rc.right; pt.y=rc.bottom;
00191 ClientToScreen(hWnd,&pt);
00192 rc.right=pt.x; rc.bottom=pt.y;
00193 ClipCursor(&rc);
00194 }
00195 else if(tracetool == 2){
00196 bToolCaptured=TRUE;
00197 SetCapture(hWnd);
00198 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00199 SetupStart();
00200 Lv=GetVertexAtCursor(LOWORD(lParam),HIWORD(lParam));
00201 }
00202 break;
00203 case WM_MOUSEMOVE:
00204 if(!bToolCaptured)break;
00205 if(tracetool == 1){
00206 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00207 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00208 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00209 }
00210 if(tracetool == 2){
00211 IterateTowardsGoal(hWnd,(int)LOWORD(lParam)-(int)LastPt.x,
00212 (int)HIWORD(lParam)-(int)LastPt.y);
00213 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00214 }
00215 break;
00216 case WM_LBUTTONUP:
00217 if(!bToolCaptured)break;
00218 if(tracetool == 1){
00219 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00220 if(Lv >= 0)DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00221 AddTraceVertex((int)LOWORD(lParam),(int)HIWORD(lParam));
00222 DrawList(hWnd,NULL);
00223 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00224 }
00225 else if(tracetool == 2){
00226 ReleaseCapture();
00227 bToolCaptured=FALSE;
00228 }
00229 break;
00230 case WM_PAINT:
00231 hDC = BeginPaint(hWnd, &ps);
00232 GetClientRect(hWnd,&rc);
00233 PatBlt(hDC,0,0,rc.right,rc.bottom,PATCOPY);
00234 DrawList(hWnd,hDC);
00235 EndPaint(hWnd,&ps);
00236 break ;
00237 case WM_SIZE:
00238 InvalidateRect(hWnd,NULL,FALSE);
00239 return 0;
00240 default:
00241 return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
00242 }
00243 return 0L ;
00244 }
00245
00246 BOOL MenuCommand(HWND hWnd, WORD id){
00247 int i;
00248 switch (id) {
00249 case IDM_PEN_RED : pen=0; goto PENID;
00250 case IDM_PEN_WHITE: pen=1; goto PENID;
00251 case IDM_PEN_BLACK: pen=2; goto PENID;
00252 case IDM_PEN_CYAN : pen=3; goto PENID;
00253 PENID:
00254 CheckMenuItem(GetMenu(hWnd),IDM_PEN_RED,MF_UNCHECKED);
00255 CheckMenuItem(GetMenu(hWnd),IDM_PEN_WHITE,MF_UNCHECKED);
00256 CheckMenuItem(GetMenu(hWnd),IDM_PEN_BLACK,MF_UNCHECKED);
00257 CheckMenuItem(GetMenu(hWnd),IDM_PEN_CYAN,MF_UNCHECKED);
00258 if(pen == 0)CheckMenuItem(GetMenu(hWnd),IDM_PEN_RED,MF_CHECKED);
00259 if(pen == 1)CheckMenuItem(GetMenu(hWnd),IDM_PEN_WHITE,MF_CHECKED);
00260 if(pen == 2)CheckMenuItem(GetMenu(hWnd),IDM_PEN_BLACK,MF_CHECKED);
00261 if(pen == 3)CheckMenuItem(GetMenu(hWnd),IDM_PEN_CYAN,MF_CHECKED);
00262 DrawList(hWnd,NULL);
00263 break;
00264 case IDM_ADD:
00265 Lv= -1;
00266 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_GRAYED);
00267 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00268 DrawMenuBar(hWnd);
00269 tracetool=1;
00270 break;
00271 case IDM_MOVE:
00272 Lv= -1;
00273 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00274 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_GRAYED);
00275 DrawMenuBar(hWnd);
00276 tracetool=2;
00277 break;
00278 case IDM_EXIT:
00279 PostQuitMessage(0);
00280 break;
00281 default:
00282 break;
00283 }
00284 return TRUE;
00285 }
00286
00287 static void DrawRubberLine(HWND hwnd, int x, int y){
00288 HPEN hOldPen,MyPen;
00289 int oldROP;
00290 HDC hDClocal;
00291 if(Lv < 0)return;
00292 hDClocal=GetDC(hwnd);
00293 if(pen == 0)MyPen=CreatePen(PS_SOLID,0,RGB(255,0,0));
00294 if(pen == 1)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,255));
00295 if(pen == 2)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,0));
00296 if(pen == 3)MyPen=CreatePen(PS_SOLID,0,RGB(0,255,0));
00297 hOldPen=SelectObject(hDClocal,MyPen);
00298 oldROP=SetROP2(hDClocal,R2_NOT);
00299 MoveToEx(hDClocal,x,y,NULL);
00300 LineTo(hDClocal,TVlist[Lv].x,TVlist[Lv].y);
00301 SetROP2(hDClocal,oldROP);
00302 SelectObject(hDClocal,hOldPen);
00303 DeleteObject(MyPen);
00304 ReleaseDC(hwnd,hDClocal);
00305 }
00306
00307 static void DrawList(HWND hwnd, HDC hDC){
00308 int i,x,y;
00309 HPEN hOldPen,MyPen;
00310 HBRUSH hOldBrush;
00311 HDC hDClocal;
00312 if(hDC == NULL){
00313 hDClocal=GetDC(hwnd);
00314 }
00315 else hDClocal=hDC;
00316 if(pen == 0)MyPen=CreatePen(PS_SOLID,0,RGB(255,0,0));
00317 if(pen == 1)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,255));
00318 if(pen == 2)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,0));
00319 if(pen == 3)MyPen=CreatePen(PS_SOLID,0,RGB(0,255,0));
00320 hOldPen=SelectObject(hDClocal,MyPen);
00321 hOldBrush=SelectObject(hDClocal,GetStockObject(BLACK_BRUSH));
00322 if(Ne > 0 && TElist != NULL){
00323 for(i=0;i<Ne;i++){
00324 if(!TElist[i].inc)continue;
00325 x=TVlist[TElist[i].v1].x; y=TVlist[TElist[i].v1].y;
00326 MoveToEx(hDClocal,x,y,NULL);
00327 x=TVlist[TElist[i].v2].x; y=TVlist[TElist[i].v2].y;
00328 LineTo(hDClocal,x,y);
00329 }
00330 }
00331 if(Nv > 0 && TVlist != NULL){
00332 for(i=0;i<Nv;i++)if(TVlist[i].inc){
00333 x=TVlist[i].x; y=TVlist[i].y;
00334 MoveToEx(hDClocal,x,y,NULL);
00335 LineTo(hDClocal,x+(int)(TVlist[i].ax[0]*40),y+(int)(TVlist[i].ax[1]*40));
00336 MoveToEx(hDClocal,x,y,NULL);
00337 LineTo(hDClocal,x+(int)(TVlist[i].ay[0]*30),y+(int)(TVlist[i].ay[1]*30));
00338 Rectangle(hDClocal,
00339 TVlist[i].x-2,TVlist[i].y-2,
00340 TVlist[i].x+2,TVlist[i].y+2);
00341 }
00342 }
00343 SelectObject(hDClocal,hOldPen);
00344 SelectObject(hDClocal,hOldBrush);
00345 DeleteObject(MyPen);
00346 if(hDC == NULL){
00347 ReleaseDC(hwnd,hDClocal);
00348 }
00349 }
00350
00351 static void AddTraceVertex(int x,int y){
00352 int i,id,found=0,flag=0;
00353 vector x0={1.0,0.0,0.0},y0={0.0,1.0,0.0},z0={0.0,0.0,1.0};
00354 struct TVLIST *v;
00355 struct TELIST *e;
00356 if(Nv > 0){
00357 for(i=0;i<Nv;i++){
00358 if(TVlist[i].inc && abs(x-TVlist[i].x) < 4 && abs(y-TVlist[i].y) < 4){
00359 found=1;
00360 if(Lv >= 0)flag=1;
00361 id=i;
00362 }
00363 }
00364 }
00365 if(!found){
00366 if(TVlist == NULL){
00367 if((v=(struct TVLIST *)X__Malloc(sizeof(struct TVLIST))) == NULL)return;
00368 }
00369 else{
00370 if((v=(struct TVLIST *)X__Realloc(TVlist,(Nv+1)*sizeof(struct TVLIST))) == NULL)return;
00371 }
00372 TVlist=v;
00373 v[Nv].x=x; v[Nv].y=y; v[Nv].z=0; v[Nv].inc=TRUE;
00374 v[Nv].p[0]=(double)x;
00375 v[Nv].p[1]=(double)y;
00376 v[Nv].p[2]=0.0;
00377 VECCOPY(x0,v[Nv].ax)
00378 VECCOPY(y0,v[Nv].ay)
00379 VECCOPY(z0,v[Nv].az)
00380 id=Nv;
00381 Nv++;
00382 }
00383 if(Lv < 0){
00384 Lv=id;
00385 }
00386 else{
00387 if(TElist == NULL){
00388 if((e=(struct TELIST *)X__Malloc(sizeof(struct TELIST))) == NULL)return;
00389 }
00390 else{
00391 if((e=(struct TELIST *)X__Realloc(TElist,(Ne+1)*sizeof(struct TELIST))) == NULL)return;
00392 }
00393 TElist=e;
00394 e[Ne].v1=id; e[Ne].v2=Lv; e[Ne].inc=TRUE;
00395 Lv=id;
00396 Ne++;
00397 }
00398 if(flag)Lv= -1;
00399 }
00400
00401 static int GetVertexAtCursor(int x, int y){
00402 int i,id=Nv-1;
00403 if(Nv > 0)for(i=0;i<Nv;i++){
00404 if(TVlist[i].inc && abs(x-TVlist[i].x) < 4 && abs(y-TVlist[i].y) < 4)id=i;
00405 }
00406 return id;
00407 }
00408
00409 static void IterateTowardsGoal(HWND hWnd,int xi, int yi){
00410 double *J,*Jt,*dTheta,*I,*dI,*Ji;
00411 double l,dl,x[3],dx[3],dx_sum[3];
00412 double;
00413 long Nv1,i,j,k,n=0;
00414 if(Lv < 0)return;
00415 Nv1=Nv-1;
00416 Nv1=Lv;
00417
00418
00419
00420
00421 x[0]=TVlist[Nv1].p[0]+(double)xi;
00422 x[1]=TVlist[Nv1].p[1]+(double)yi;
00423 x[2]=TVlist[Nv1].p[2]+(double)0.0;
00424 VECSUB(x,TVlist[Nv1].p,dx)
00425 if((dTheta=(double *)malloc((3*Nv1)*sizeof(double))) == NULL)return;
00426 if((J=(double *)malloc(3*(3*Nv1)*sizeof(double))) == NULL)return;
00427 if((Jt=(double *)malloc((3*Nv1)*3*sizeof(double))) == NULL)return;
00428 if((Ji=(double *)malloc((3*Nv1)*3*sizeof(double))) == NULL)return;
00429 if((dI=(double *)malloc(3*3*sizeof(double))) == NULL)return;
00430 if((I=(double *)malloc(3*3*sizeof(double))) == NULL)return;
00431
00432 sprintf(filename,"f:\\ik3d%ld.dat",version); version++;
00433
00434 while(1){
00435 VECSUB(x,TVlist[Nv1].p,dx)
00436 if(++n > 200){MessageBox(NULL,"Out of iteration",NULL,MB_OK); break;}
00437 if(debug != NULL)fprintf(debug,"Iteration %ld\n",n);
00438 CalculateJacobian(J,Nv1);
00439 CalculateTranspose(J,Jt,3,3*Nv1);
00440 MultiplyMatrix(J,3,3*Nv1,Jt,3*Nv1,3,I);
00441 if(InvertMatrix(I,3,dI)){
00442
00443 MultiplyMatrix(Jt,3*Nv1,3,dI,3,3,Ji);
00444
00445
00446
00447 if(!StepOK(J,Ji,dx,3,3*Nv1,1.e-2,1.e-6)){
00448 MessageBox(NULL,"Dx too small",NULL,MB_OK);
00449 break;
00450 }
00451 else{
00452
00453 MultiplyMatrix(Ji,3*Nv1,3,dx,3,1,dTheta);
00454
00455 UpdateTheLinkage(Nv1,dTheta);
00456
00457
00458
00459
00460 if(Dist(TVlist[Nv1].p,x,3) < 3.0){
00461 break;
00462 }
00463 }
00464 }
00465 else{
00466 MessageBeep(MB_OK);
00467 }
00468 }
00469
00470 if(debug != NULL)fclose(debug);
00471 free(dTheta);
00472 free(Ji);
00473 free(I);
00474 free(dI);
00475 free(Jt);
00476 free(J);
00477 InvalidateRect(hWnd,NULL,FALSE);
00478 return;
00479 }
00480
00481 static void CalculateJacobian(double *J,
00482 long n
00483
00484 ){
00485 long k,l;
00486 vector ax,ay,az,dp,Jx,Jy,Jz;
00487 for(l=0,k=0;k<n;k++){
00488 VECCOPY(TVlist[k].ax,ax)
00489 VECCOPY(TVlist[k].ay,ay)
00490 VECCOPY(TVlist[k].az,az)
00491 VECSUB(TVlist[n].p,TVlist[k].p,dp)
00492 CROSS(ax,dp,Jx)
00493 CROSS(ay,dp,Jy)
00494 CROSS(az,dp,Jz)
00495 J[l] = Jx[0];
00496 J[l+n*3] = Jx[1];
00497 J[l+n*3*2] = Jx[2];
00498 l++;
00499 J[l] = Jy[0];
00500 J[l+n*3] = Jy[1];
00501 J[l+n*3*2] = Jy[2];
00502 l++;
00503 J[l] = Jz[0];
00504 J[l+n*3] = Jz[1];
00505 J[l+n*3*2] = Jz[2];
00506 l++;
00507 }
00508 return;
00509 }
00510
00511 static void SetupStart(void){
00512 int i;
00513 vector x0={1.0,0.0,0.0},y0={0.0,1.0,0.0},z0={0.0,0.0,1.0};
00514 if(Nv < 2)return;
00515 for(i=0;i<Nv;i++){
00516 TVlist[i].p[0]=(double)TVlist[i].x;
00517 TVlist[i].p[1]=(double)TVlist[i].y;
00518 TVlist[i].p[2]=0.0;
00519 VECCOPY(x0,TVlist[i].ax)
00520 VECCOPY(y0,TVlist[i].ay)
00521 VECCOPY(z0,TVlist[i].az)
00522 }
00523 }
00524
00525 static void UpdateTheLinkage(long Nv1, double *dTheta){
00526 long i,j,l;
00527 double thetaX,thetaY,thetaZ;
00528 vector ax,ay,az,baseZero={0.0,0.0,0.0};
00529 for(i=0,l=0;i<Nv1;i++,l+=3){
00530
00531
00532 thetaX = *(dTheta+l);
00533 thetaY = *(dTheta+l+1);
00534 thetaZ = *(dTheta+l+2);
00535 VECCOPY(TVlist[i].ax,ax)
00536 VECCOPY(TVlist[i].ay,ay)
00537 VECCOPY(TVlist[i].az,az)
00538
00539
00540 for(j=i+1;j<=Nv1;j++){
00541 RotateVectorRound(TVlist[j].p,TVlist[i].p,ax,thetaX);
00542 RotateVectorRound(TVlist[j].p,TVlist[i].p,ay,thetaY);
00543 RotateVectorRound(TVlist[j].p,TVlist[i].p,az,thetaZ);
00544 RotateVectorRound(TVlist[j].ax,baseZero,ax,thetaX);
00545 RotateVectorRound(TVlist[j].ax,baseZero,ay,thetaY);
00546 RotateVectorRound(TVlist[j].ax,baseZero,az,thetaZ);
00547
00548
00549 RotateVectorRound(TVlist[j].ay,baseZero,ax,thetaX);
00550 RotateVectorRound(TVlist[j].ay,baseZero,ay,thetaY);
00551 RotateVectorRound(TVlist[j].ay,baseZero,az,thetaZ);
00552 RotateVectorRound(TVlist[j].az,baseZero,ax,thetaX);
00553 RotateVectorRound(TVlist[j].az,baseZero,ay,thetaY);
00554 RotateVectorRound(TVlist[j].az,baseZero,az,thetaZ);
00555 TVlist[j].x=(int)TVlist[j].p[0];
00556 TVlist[j].y=(int)TVlist[j].p[1];
00557 TVlist[j].z=(int)TVlist[j].p[2];
00558 }
00559 }
00560 return;
00561 }
00562
00563 static BOOL StepOK(double *J, double *Ji, double *dx,
00564 long n, long m,
00565 double e, double dmin){
00566 BOOL result=TRUE;
00567 long i;
00568 double *I,*N,norm=0.0;
00569 if((I=(double *)malloc(n*n*sizeof(double))) == NULL)return FALSE;
00570 if((N=(double *)malloc(n*sizeof(double))) == NULL)return FALSE;
00571 MultiplyMatrix(J,n,m,Ji,m,n,I);
00572 for(i=0;i<n;i++){
00573 I[i*n+i] -= 1.0;
00574 }
00575 while(1){
00576 MultiplyMatrix(I,n,n,dx,n,1,N);
00577 norm=0.0;
00578 for(i=0;i<n;i++){
00579 norm += N[i] * N[i];
00580 }
00581 if(norm < e)break;
00582 for(i=0;i<n;i++)dx[i] *= 0.5;
00583 if(Length(dx,n) < dmin){
00584 result=FALSE;
00585 break;
00586 }
00587 }
00588 free(N);
00589 free(I);
00590 return result;
00591 }
00592
00593 static void RotateVectorRound(vector v,
00594 vector BaseOfRotation,
00595 vector AxisOfRotation,
00596 double theta){
00597
00598 double t[4][4];
00599 vector lv,lvv;
00600 VECSUB(v,BaseOfRotation,lv)
00601 rotate_round_vector(theta,AxisOfRotation,t);
00602 mv4by1(t,lv,lvv);
00603 VECSUM(lvv,BaseOfRotation,v)
00604 return;
00605 }
00606
00607 static BOOL normalize(vector v){
00608 double n,nn;
00609 n= (double)((v[0]*v[0]) + (v[1]*v[1]) + (v[2]*v[2]));
00610 if(n < 1.e-10)return FALSE;
00611 nn=sqrt(n);
00612 n = 1.0 / nn;
00613 VECSCALE(n,v,v)
00614 return TRUE;
00615 }
00616
00617
00618 static void rotz(double tr[4][4], double ang){
00619 short i,j;
00620 for(i=0;i<4;i++)
00621 for(j=0;j<4;j++){
00622 tr[i][j]=0.0;
00623 if(i == j)tr[i][j]=1.0;
00624 }
00625 tr[0][0]= cos(ang);
00626 tr[0][1]=-sin(ang);
00627 tr[1][0]= sin(ang);
00628 tr[1][1]= cos(ang);
00629 return;
00630 }
00631
00632 static void roty(double tr[4][4], double ang){
00633 short i,j;
00634 for(i=0;i<4;i++)
00635 for(j=0;j<4;j++){
00636 tr[i][j]=0.0;
00637 if(i == j)tr[i][j]=1.0;
00638 }
00639 tr[0][0]= cos(ang);
00640 tr[0][2]=-sin(ang);
00641 tr[2][0]= sin(ang);
00642 tr[2][2]= cos(ang);
00643 return;
00644 }
00645
00646 static void rotx(double tr[4][4], double ang){
00647 long i,j;
00648 for(i=0;i<4;i++)
00649 for(j=0;j<4;j++){
00650 tr[i][j]=0.0;
00651 if(i == j)tr[i][j]=1.0;
00652 }
00653 tr[1][1]= cos(ang);
00654 tr[1][2]=-sin(ang);
00655 tr[2][1]= sin(ang);
00656 tr[2][2]= cos(ang);
00657 return;
00658 }
00659
00660 static void mv4by1(double t4[4][4], vector v1, vector v2){
00661 double xx,yy,zz;
00662 xx=t4[0][0]*v1[0]+t4[0][1]*v1[1]+t4[0][2]*v1[2]+t4[0][3];
00663 yy=t4[1][0]*v1[0]+t4[1][1]*v1[1]+t4[1][2]*v1[2]+t4[1][3];
00664 zz=t4[2][0]*v1[0]+t4[2][1]*v1[1]+t4[2][2]*v1[2]+t4[2][3];
00665 v2[0]=xx; v2[1]=yy; v2[2]=zz;
00666 return;
00667 }
00668
00669 static void m4by4(double t1[4][4], double t2[4][4], double tr[4][4]){
00670 short n=4,i,j,k;
00671 for(i=0;i<4;i++)
00672 for(j=0;j<4;j++){
00673 tr[i][j]=0.0;
00674 for(k=0;k<4;k++)tr[i][j]=tr[i][j]+t1[i][k]*t2[k][j];
00675 }
00676 return;
00677 }
00678
00679 static void rotate_round_vector(double angle, vector v, double t[4][4]){
00680 double dx,dy,dz,phi,theta,dxy;
00681 double t1[4][4],t2[4][4],t3[4][4];
00682 dx=v[0]; dy=v[1]; dz=v[2];
00683 dxy=dx*dx+dy*dy;
00684 if(dxy < 0.00001){
00685 if(dz > 0.0)rotz(t, angle);
00686 else rotz(t,-angle);
00687 return;
00688 }
00689 dxy=sqrt(dxy);
00690 if (dx == 0.0 && dy > 0.0)phi = PI2;
00691 else if(dx == 0.0 && dy < 0.0)phi = -PI2;
00692 else phi = atan2(dy,dx);
00693 theta = atan2(dz,dxy);
00694 rotz(t3, -phi);
00695 roty(t2, -theta);
00696 m4by4(t2,t3,t1);
00697 rotx(t2, angle);
00698 m4by4(t2,t1,t3);
00699 roty(t2,theta);
00700 m4by4(t2,t3,t1);
00701 rotz(t2,phi);
00702 m4by4(t2,t1,t);
00703 }
00704
00705 static double Length(double *dx, long n){
00706 long i;
00707 double l=0.0;
00708 for(i=0;i<n;i++)l += dx[i]*dx[i];
00709 return sqrt(l);
00710 }
00711
00712 static double Dist(double *x, double *y, long n){
00713 long i;
00714 double d=0.0;
00715 for(i=0;i<n;i++)d += (x[i]-y[i])*(x[i]-y[i]);
00716 return sqrt(d);
00717 }
00718
00719 static void CalculateTranspose(double *M, double *Mt, long n, long m){
00720 long i,j;
00721 for(i=0;i<n;i++){
00722 for(j=0;j<m;j++){
00723 *(Mt+j*n+i) = *(M+i*m+j);
00724 }
00725 }
00726 return;
00727 }
00728
00729 static void MultiplyMatrix(double *M1, long n1, long m1,
00730 double *M2, long n2, long m2,
00731 double *I){
00732 long i,j,k,c;
00733 double s;
00734 if(m1 != n2){MessageBox(NULL,"Bad Multiply",NULL,MB_OK); return;}
00735 c=n2;
00736 for(i=0;i<n1;i++){
00737 for(j=0;j<m2;j++){
00738 for(s=0.0,k=0;k<c;k++){
00739 s += (*(M1+i*m1+k)) * (*(M2+k*m2+j));
00740
00741 }
00742 *(I+i*m2+j) = s;
00743 }
00744 }
00745 return;
00746 }
00747
00748 static BOOL InvertMatrix(double *A, long n, double *B){
00749 int i,j,k,imax,kp1;
00750 double del,amax,atmp,btmp,div,amult,eps=1.e-6;
00751 for(i=0;i<n;i++)for(j=0;j<n;j++){
00752 if(i == j)B[i*n+j]=1.0;
00753 else B[i*n+j]=0.0;
00754 }
00755 del=1.0;
00756 for(k=0;k<n;k++){
00757 if(k < n-1){
00758 imax=k;
00759 amax=fabs(A[k*n+k]);
00760 kp1=k+1;
00761 for(i=kp1;i<n;i++){
00762 if(amax-fabs(A[i*n+k]) < 0.0){
00763 imax=i;
00764 amax=fabs(A[i*n+k]);
00765 }
00766 }
00767 if(imax != k){
00768 for(j=0;j<n;j++){
00769 atmp=A[imax*n+j];
00770 A[imax*n+j]=A[k*n+j];
00771 A[k*n+j]=atmp;
00772 btmp=B[imax*n+j];
00773 B[imax*n+j]=B[k*n+j];
00774 B[k*n+j]=btmp;
00775 }
00776 del = -del;
00777 }
00778 }
00779 if(fabs(A[k*n+k]) < eps)return FALSE;
00780 del=A[k*n+k]*del;
00781 div=1.0/A[k*n+k];
00782 for(j=0;j<n;j++){
00783 A[k*n+j]=A[k*n+j]*div;
00784 B[k*n+j]=B[k*n+j]*div;
00785 }
00786 for(i=0;i<n;i++){
00787 amult=A[i*n+k];
00788 if(i != k){
00789 for(j=0;j<n;j++){
00790 A[i*n+j]=A[i*n+j]-amult*A[k*n+j];
00791 B[i*n+j]=B[i*n+j]-amult*B[k*n+j];
00792 }
00793 }
00794 }
00795 }
00796 return TRUE;
00797 }
00798
00799 #if __WATCOMC__
00800 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00801 #else
00802 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00803 #endif
00804 switch (dwReason) {
00805 case DLL_PROCESS_ATTACH: {
00806 hThisInstance=hDLL;
00807 break;
00808 }
00809 case DLL_PROCESS_DETACH:
00810 break;
00811 }
00812 return TRUE;
00813 }
00814
00815 BOOL _Xmodeler
00816 (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00817 lpEVI=lpevi;
00818 tracetool=0;
00819 hParent=parent_window;
00820 return Tester();
00821 }