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 "ik2d.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 static HWND hParent;
00053 static HINSTANCE hThisInstance;
00054 static char *szViewClass="OFX:DraftClass";
00055 static SYSTEM_INFO sys_info;
00056 static int xScreen,yScreen;
00057 static DWORD fdwStyle = WS_POPUP | WS_CAPTION | ! WS_SYSMENU |
00058 WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
00059 static HCURSOR hcurSave,hcurPen1=NULL;
00060
00061 static int pen=0,stretched=1,tracetool=0;
00062 static long Lv= -1,Fv= -1,Nv=0,Ne=0;
00063 static struct TVLIST {BOOL inc; int x,y; long id; double l;
00064 vector d; double theta;} *TVlist=NULL;
00065 static struct TELIST {BOOL inc; int v1,v2;} *TElist=NULL;
00066
00067 static LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
00068 static BOOL MenuCommand(HWND, WORD);
00069 static BOOL Tester(void);
00070 static void DrawRubberLine(HWND, int, int);
00071 static void DrawList(HWND, HDC);
00072 static void AddTraceVertex(int, int);
00073 static int GetVertexAtCursor(int, int);
00074 static void MoveVertex(HWND, int, int);
00075 static void GetLengthAndAngles(void);
00076 static BOOL TwoCross(vector, vector);
00077 static void CalculateTranspose(double *, double *, long, long);
00078 static void MultiplyMatrix(double *, long, long,
00079 double *, long, long,
00080 double *);
00081 static BOOL InvertMatrix(double *, long, double *);
00082 static BOOL StepOK(double *, double *, double *, long, long, double, double);
00083 static void CalculateJacobian(double *, long);
00084 static double Length(double *, long);
00085 static double Dist(double *, double *, long);
00086
00087 static BOOL Tester(void){
00088 MSG msg;
00089 HWND hDesktopWnd,hWnd;
00090 HDC hDCcaps;
00091 WNDCLASS wndclass;
00092 TVlist=NULL; TElist=NULL; Nv=0; Ne=0;
00093 hDesktopWnd = GetDesktopWindow();
00094 hDCcaps = GetDC(hDesktopWnd);
00095 ReleaseDC(hDesktopWnd,hDCcaps);
00096 GetSystemInfo(&sys_info);
00097 wndclass.style = 0;
00098 wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
00099 wndclass.cbClsExtra = 0 ;
00100 wndclass.cbWndExtra = 0 ;
00101 wndclass.hInstance = hThisInstance ;
00102 wndclass.hIcon = NULL;
00103 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
00104 wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
00105 wndclass.lpszMenuName = "tracemenu" ;
00106 wndclass.lpszClassName = szViewClass;
00107 if (!RegisterClass (&wndclass)) return FALSE ;
00108 xScreen = GetSystemMetrics(SM_CXSCREEN) ;
00109 yScreen = GetSystemMetrics(SM_CYSCREEN) ;
00110 hWnd = CreateWindow(
00111 szViewClass,
00112 "2D Inverse Kinematics (IK) Test Engine",
00113 fdwStyle,
00114 25,
00115 25,
00116 xScreen-50,
00117 yScreen-50,
00118 hParent,
00119 NULL,
00120 hThisInstance,
00121 NULL) ;
00122 if(hWnd == NULL)return FALSE;
00123 hcurPen1=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PEN1));
00124 ShowWindow (hWnd,SW_SHOWNA);
00125 PostMessage(hWnd,WM_COMMAND,(WPARAM)IDM_DRAWIT,0);
00126 while(GetMessage (&msg,NULL,0,0)){
00127 TranslateMessage (&msg);
00128 DispatchMessage (&msg);
00129 }
00130 DestroyWindow(hWnd);
00131 if(hcurPen1 != NULL)DeleteObject(hcurPen1);
00132 UnregisterClass(wndclass.lpszClassName,wndclass.hInstance);
00133 if(TVlist != NULL)X__Free(TVlist); TVlist=NULL; Nv=0;
00134 if(TElist != NULL)X__Free(TElist); TElist=NULL; Ne=0;
00135 return TRUE;
00136 }
00137
00138 LRESULT CALLBACK MainWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,
00139 LPARAM lParam){
00140 static BOOL bToolCaptured=FALSE;
00141 static HCURSOR hCursorSave;
00142 static POINT LastPt;
00143 PAINTSTRUCT ps;
00144 HDC hDC;
00145 int i;
00146 RECT rc;
00147 POINT pt;
00148 switch (iMessage) {
00149 case WM_DESTROY:
00150 break;
00151 case WM_COMMAND:
00152 return MenuCommand(hWnd,LOWORD(wParam));
00153 break;
00154 case WM_RBUTTONUP:
00155 if(!bToolCaptured)break;
00156 if(tracetool == 1){
00157 DrawRubberLine(hWnd,LOWORD(lParam),HIWORD(lParam));
00158 SetCursor(hCursorSave);
00159 ClipCursor(NULL);
00160 ReleaseCapture();
00161 bToolCaptured=FALSE;
00162 Lv= -1;
00163 }
00164 break;
00165 case WM_LBUTTONDOWN:
00166 if(bToolCaptured)break;
00167 if(tracetool == 1){
00168 bToolCaptured=TRUE;
00169 SetCapture(hWnd);
00170 hCursorSave=SetCursor(hcurPen1);
00171 GetClientRect(hWnd,&rc);
00172 pt.x=rc.left; pt.y=rc.top;
00173 ClientToScreen(hWnd,&pt);
00174 rc.left=pt.x; rc.top=pt.y;
00175 pt.x=rc.right; pt.y=rc.bottom;
00176 ClientToScreen(hWnd,&pt);
00177 rc.right=pt.x; rc.bottom=pt.y;
00178 ClipCursor(&rc);
00179 }
00180 else if(tracetool == 2){
00181 bToolCaptured=TRUE;
00182 SetCapture(hWnd);
00183 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00184 GetLengthAndAngles();
00185 Lv=GetVertexAtCursor(LOWORD(lParam),HIWORD(lParam));
00186 }
00187 break;
00188 case WM_MOUSEMOVE:
00189 if(!bToolCaptured)break;
00190 if(tracetool == 1){
00191 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00192 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00193 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00194 }
00195 if(tracetool == 2){
00196 MoveVertex(hWnd,(int)LOWORD(lParam)-(int)LastPt.x,
00197 (int)HIWORD(lParam)-(int)LastPt.y);
00198 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00199 }
00200 break;
00201 case WM_LBUTTONUP:
00202 if(!bToolCaptured)break;
00203 if(tracetool == 1){
00204 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00205 if(Lv >= 0)DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00206 AddTraceVertex((int)LOWORD(lParam),(int)HIWORD(lParam));
00207 DrawList(hWnd,NULL);
00208 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00209 }
00210 else if(tracetool == 2){
00211 ReleaseCapture();
00212 bToolCaptured=FALSE;
00213 }
00214 break;
00215 case WM_PAINT:
00216 hDC = BeginPaint(hWnd, &ps);
00217 GetClientRect(hWnd,&rc);
00218 PatBlt(hDC,0,0,rc.right,rc.bottom,PATCOPY);
00219 DrawList(hWnd,hDC);
00220 EndPaint(hWnd,&ps);
00221 break ;
00222 case WM_SIZE:
00223 InvalidateRect(hWnd,NULL,FALSE);
00224 return 0;
00225 default:
00226 return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
00227 }
00228 return 0L ;
00229 }
00230
00231 BOOL MenuCommand(HWND hWnd, WORD id){
00232 int i;
00233 switch (id) {
00234 case IDM_PEN_RED : pen=0; goto PENID;
00235 case IDM_PEN_WHITE: pen=1; goto PENID;
00236 case IDM_PEN_BLACK: pen=2; goto PENID;
00237 case IDM_PEN_CYAN : pen=3; goto PENID;
00238 PENID:
00239 CheckMenuItem(GetMenu(hWnd),IDM_PEN_RED,MF_UNCHECKED);
00240 CheckMenuItem(GetMenu(hWnd),IDM_PEN_WHITE,MF_UNCHECKED);
00241 CheckMenuItem(GetMenu(hWnd),IDM_PEN_BLACK,MF_UNCHECKED);
00242 CheckMenuItem(GetMenu(hWnd),IDM_PEN_CYAN,MF_UNCHECKED);
00243 if(pen == 0)CheckMenuItem(GetMenu(hWnd),IDM_PEN_RED,MF_CHECKED);
00244 if(pen == 1)CheckMenuItem(GetMenu(hWnd),IDM_PEN_WHITE,MF_CHECKED);
00245 if(pen == 2)CheckMenuItem(GetMenu(hWnd),IDM_PEN_BLACK,MF_CHECKED);
00246 if(pen == 3)CheckMenuItem(GetMenu(hWnd),IDM_PEN_CYAN,MF_CHECKED);
00247 DrawList(hWnd,NULL);
00248 break;
00249 case IDM_ADD:
00250 Lv= -1;
00251 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_GRAYED);
00252 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00253 DrawMenuBar(hWnd);
00254 tracetool=1;
00255 break;
00256 case IDM_MOVE:
00257 Lv= -1;
00258 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00259 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_GRAYED);
00260 DrawMenuBar(hWnd);
00261 tracetool=2;
00262 break;
00263 case IDM_EXIT:
00264 PostQuitMessage(0);
00265 break;
00266 default:
00267 break;
00268 }
00269 return TRUE;
00270 }
00271
00272 static void DrawRubberLine(HWND hwnd, int x, int y){
00273 HPEN hOldPen,MyPen;
00274 int oldROP;
00275 HDC hDClocal;
00276 if(Lv < 0)return;
00277 hDClocal=GetDC(hwnd);
00278 if(pen == 0)MyPen=CreatePen(PS_SOLID,0,RGB(255,0,0));
00279 if(pen == 1)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,255));
00280 if(pen == 2)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,0));
00281 if(pen == 3)MyPen=CreatePen(PS_SOLID,0,RGB(0,255,0));
00282 hOldPen=SelectObject(hDClocal,MyPen);
00283 oldROP=SetROP2(hDClocal,R2_NOT);
00284 MoveToEx(hDClocal,x,y,NULL);
00285 LineTo(hDClocal,TVlist[Lv].x,TVlist[Lv].y);
00286 SetROP2(hDClocal,oldROP);
00287 SelectObject(hDClocal,hOldPen);
00288 DeleteObject(MyPen);
00289 ReleaseDC(hwnd,hDClocal);
00290 }
00291
00292 static void DrawList(HWND hwnd, HDC hDC){
00293 int i,x,y;
00294 HPEN hOldPen,MyPen;
00295 HBRUSH hOldBrush;
00296 HDC hDClocal;
00297 if(hDC == NULL){
00298 hDClocal=GetDC(hwnd);
00299 }
00300 else hDClocal=hDC;
00301 if(pen == 0)MyPen=CreatePen(PS_SOLID,0,RGB(255,0,0));
00302 if(pen == 1)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,255));
00303 if(pen == 2)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,0));
00304 if(pen == 3)MyPen=CreatePen(PS_SOLID,0,RGB(0,255,0));
00305 hOldPen=SelectObject(hDClocal,MyPen);
00306 hOldBrush=SelectObject(hDClocal,GetStockObject(BLACK_BRUSH));
00307 if(Ne > 0 && TElist != NULL){
00308 for(i=0;i<Ne;i++){
00309 if(!TElist[i].inc)continue;
00310 x=TVlist[TElist[i].v1].x; y=TVlist[TElist[i].v1].y;
00311 MoveToEx(hDClocal,x,y,NULL);
00312 x=TVlist[TElist[i].v2].x; y=TVlist[TElist[i].v2].y;
00313 LineTo(hDClocal,x,y);
00314 }
00315 }
00316 if(Nv > 0 && TVlist != NULL){
00317 for(i=0;i<Nv;i++)if(TVlist[i].inc)Rectangle(hDClocal,
00318 TVlist[i].x-2,TVlist[i].y-2,TVlist[i].x+2,TVlist[i].y+2);
00319 }
00320 SelectObject(hDClocal,hOldPen);
00321 SelectObject(hDClocal,hOldBrush);
00322 DeleteObject(MyPen);
00323 if(hDC == NULL){
00324 ReleaseDC(hwnd,hDClocal);
00325 }
00326 }
00327
00328 static void AddTraceVertex(int x,int y){
00329 int i,id,found=0,flag=0;
00330 struct TVLIST *v;
00331 struct TELIST *e;
00332 if(Nv > 0){
00333 for(i=0;i<Nv;i++){
00334 if(TVlist[i].inc && abs(x-TVlist[i].x) < 4 && abs(y-TVlist[i].y) < 4){
00335 found=1;
00336 if(Lv >= 0)flag=1;
00337 id=i;
00338 }
00339 }
00340 }
00341 if(!found){
00342 if(TVlist == NULL){
00343 if((v=(struct TVLIST *)X__Malloc(sizeof(struct TVLIST))) == NULL)return;
00344 }
00345 else{
00346 if((v=(struct TVLIST *)X__Realloc(TVlist,(Nv+1)*sizeof(struct TVLIST))) == NULL)return;
00347 }
00348 TVlist=v;
00349 v[Nv].x=x; v[Nv].y=y; v[Nv].inc=TRUE;
00350 id=Nv;
00351 Nv++;
00352 }
00353 if(Lv < 0){
00354 Lv=id;
00355 }
00356 else{
00357 if(TElist == NULL){
00358 if((e=(struct TELIST *)X__Malloc(sizeof(struct TELIST))) == NULL)return;
00359 }
00360 else{
00361 if((e=(struct TELIST *)X__Realloc(TElist,(Ne+1)*sizeof(struct TELIST))) == NULL)return;
00362 }
00363 TElist=e;
00364 e[Ne].v1=id; e[Ne].v2=Lv; e[Ne].inc=TRUE;
00365 Lv=id;
00366 Ne++;
00367 }
00368 if(flag)Lv= -1;
00369 }
00370
00371 static int GetVertexAtCursor(int x, int y){
00372 int i,id=Nv-1;
00373 if(Nv > 0)for(i=0;i<Nv;i++){
00374 if(TVlist[i].inc && abs(x-TVlist[i].x) < 4 && abs(y-TVlist[i].y) < 4)id=i;
00375 }
00376 return id;
00377 }
00378
00379 static void MoveVertex(HWND hWnd,int xi, int yi){
00380 double *J,*Jt,*dTheta,*I,*dI,*Ji;
00381 double l,dl,x[2],dx[2],dx_sum[2];
00382 double nx,ny,angle;
00383 long Nv1,i,j,k,n=0;
00384 if(Lv < 0)return;
00385 Nv1=Nv-1;
00386 Nv1=Lv;
00387 dx_sum[0]=dx_sum[1]=0.0;
00388 x[0]=dx[0]=(double)xi; x[1]=dx[1]=(double)yi;
00389
00390 #if 1
00391 x[0] = (double)TVlist[Nv1].x+dx[0]; x[1] = (double)TVlist[Nv1].y+dx[1];
00392 #endif
00393
00394 if((dTheta=(double *)malloc((Nv1)*sizeof(double))) == NULL)return;
00395 if((J=(double *)malloc(2*(Nv1)*sizeof(double))) == NULL)return;
00396 if((Jt=(double *)malloc((Nv1)*2*sizeof(double))) == NULL)return;
00397 if((Ji=(double *)malloc((Nv1)*2*sizeof(double))) == NULL)return;
00398 if((dI=(double *)malloc(2*2*sizeof(double))) == NULL)return;
00399 if((I=(double *)malloc(2*2*sizeof(double))) == NULL)return;
00400 while(1){
00401 if(++n > 1000){ break;}
00402 CalculateJacobian(J,Nv1);
00403
00404
00405
00406
00407
00408
00409
00410
00411 CalculateTranspose(J,Jt,2,Nv1);
00412 MultiplyMatrix(J,2,Nv1,Jt,Nv1,2,I);
00413 if(InvertMatrix(I,2,dI)){
00414 MultiplyMatrix(Jt,Nv1,2,dI,2,2,Ji);
00415 if(!StepOK(J,Ji,dx,2,Nv1,0.01,1.e-6)){
00416 MessageBox(NULL,"Dx too small",NULL,MB_OK);
00417 break;
00418 }
00419 else{
00420 MultiplyMatrix(Ji,Nv1,2,dx,2,1,dTheta);
00421
00422
00423
00424
00425 for(i=0;i<Nv1;i++)TVlist[i].theta += dTheta[i];
00426
00427 #if 1
00428 nx=(double)TVlist[0].x;
00429 ny=(double)TVlist[0].y;
00430 angle=0.0;
00431 for(i=1;i<Nv;i++){
00432 angle += TVlist[i-1].theta;
00433 nx += TVlist[i-1].l * cos(angle);
00434 ny += TVlist[i-1].l * sin(angle);
00435 TVlist[i].x=(int)nx;
00436 TVlist[i].y=(int)ny;
00437 }
00438 dx_sum[0] = (double)TVlist[Nv1].x; dx_sum[1] = (double)TVlist[Nv1].y;
00439 dx[0]=x[0]-dx_sum[0]; dx[1]=x[1]-dx_sum[1];
00440 #else
00441 dx_sum[0] += dx[0]; dx_sum[1] += dx[1];
00442 #endif
00443
00444 if(Dist(dx_sum,x,2) < 1.0)break;
00445 }
00446 }
00447 else{
00448 MessageBeep(MB_OK);
00449 }
00450 }
00451
00452
00453
00454
00455 #if 0
00456 nx=(double)TVlist[0].x;
00457 ny=(double)TVlist[0].y;
00458 angle=0.0;
00459 for(i=1;i<Nv;i++){
00460 angle += TVlist[i-1].theta;
00461 nx += TVlist[i-1].l * cos(angle);
00462 ny += TVlist[i-1].l * sin(angle);
00463 TVlist[i].x=(int)nx;
00464 TVlist[i].y=(int)ny;
00465 }
00466 #endif
00467
00468
00469
00470 free(dTheta);
00471 free(Ji);
00472 free(I);
00473 free(dI);
00474 free(Jt);
00475 free(J);
00476 InvalidateRect(hWnd,NULL,FALSE);
00477 return;
00478 }
00479
00480 static void CalculateJacobian(double *J, long n){
00481 long i,j,k;
00482 double sumx,sumy,angle;
00483 for(k=0;k<n;k++){
00484 sumx=sumy=0.0;
00485 for(i=k;i<n;i++){
00486 angle=0.0;
00487 for(j=0;j<=i;j++)angle += TVlist[j].theta;
00488 sumx += TVlist[i].l * sin(angle);
00489 sumy += TVlist[i].l * cos(angle);
00490 }
00491 J[k] = -sumx;
00492 J[n+k]=sumy;
00493 }
00494 return;
00495 }
00496
00497 static double Length(double *dx, long n){
00498 long i;
00499 double l=0.0;
00500 for(i=0;i<n;i++)l += dx[i]*dx[i];
00501 return sqrt(l);
00502 }
00503
00504 static double Dist(double *x, double *y, long n){
00505 long i;
00506 double d=0.0;
00507 for(i=0;i<n;i++)d += (x[i]-y[i])*(x[i]-y[i]);
00508 return sqrt(d);
00509 }
00510
00511 static BOOL StepOK(double *J, double *Ji, double *dx,
00512 long n, long m,
00513 double e, double dmin){
00514 BOOL result=TRUE;
00515 long i;
00516 double *I,*N,norm=0.0;
00517 if((I=(double *)malloc(n*n*sizeof(double))) == NULL)return FALSE;
00518 if((N=(double *)malloc(n*sizeof(double))) == NULL)return FALSE;
00519 MultiplyMatrix(J,n,m,Ji,m,n,I);
00520 for(i=0;i<n;i++){
00521 I[i*n+i] -= 1.0;
00522 }
00523 while(1){
00524 MultiplyMatrix(I,n,n,dx,n,1,N);
00525 norm=0.0;
00526 for(i=0;i<n;i++){
00527 norm += N[i] * N[i];
00528 }
00529 if(norm < e)break;
00530 for(i=0;i<n;i++)dx[i] *= 0.5;
00531 if(Length(dx,n) < dmin){
00532 result=FALSE;
00533 break;
00534 }
00535 }
00536 free(N);
00537 free(I);
00538 return result;
00539 }
00540
00541 static void CalculateTranspose(double *M, double *Mt, long n, long m){
00542 long i,j;
00543 for(i=0;i<n;i++){
00544 for(j=0;j<m;j++){
00545 *(Mt+j*n+i) = *(M+i*m+j);
00546 }
00547 }
00548 return;
00549 }
00550
00551 static void MultiplyMatrix(double *M1, long n1, long m1,
00552 double *M2, long n2, long m2,
00553 double *I){
00554 long i,j,k,c;
00555 double s;
00556 if(m1 != n2){MessageBox(NULL,"Bad Multiply",NULL,MB_OK); return;}
00557 c=n2;
00558 for(i=0;i<n1;i++){
00559 for(j=0;j<m2;j++){
00560 for(s=0.0,k=0;k<c;k++){
00561 s += (*(M1+i*m1+k)) * (*(M2+k*m2+j));
00562
00563 }
00564 *(I+i*m2+j) = s;
00565 }
00566 }
00567 return;
00568 }
00569
00570 static BOOL xInvertMatrix(double *I, long n, double *dI){
00571 double det;
00572 if(n != 2)return FALSE;
00573 det=I[0]*I[3] - I[2]*I[1];
00574 if(fabs(det) < 1.e-6)return FALSE;
00575 det = 1.0/det;
00576 dI[0] = I[3]*det;
00577 dI[3] = I[0]*det;
00578 dI[1] = -I[1]*det;
00579 dI[2] = -I[2]*det;
00580 return TRUE;
00581 }
00582
00583 static BOOL InvertMatrix(double *A, long n, double *B){
00584 int i,j,k,imax,kp1;
00585 double del,amax,atmp,btmp,div,amult,eps=1.e-6;
00586 for(i=0;i<n;i++)for(j=0;j<n;j++){
00587 if(i == j)B[i*n+j]=1.0;
00588 else B[i*n+j]=0.0;
00589 }
00590 del=1.0;
00591 for(k=0;k<n;k++){
00592 if(k < n-1){
00593 imax=k;
00594 amax=fabs(A[k*n+k]);
00595 kp1=k+1;
00596 for(i=kp1;i<n;i++){
00597 if(amax-fabs(A[i*n+k]) < 0.0){
00598 imax=i;
00599 amax=fabs(A[i*n+k]);
00600 }
00601 }
00602 if(imax != k){
00603 for(j=0;j<n;j++){
00604 atmp=A[imax*n+j];
00605 A[imax*n+j]=A[k*n+j];
00606 A[k*n+j]=atmp;
00607 btmp=B[imax*n+j];
00608 B[imax*n+j]=B[k*n+j];
00609 B[k*n+j]=btmp;
00610 }
00611 del = -del;
00612 }
00613 }
00614 if(fabs(A[k*n+k]) < eps)return FALSE;
00615 del=A[k*n+k]*del;
00616 div=1.0/A[k*n+k];
00617 for(j=0;j<n;j++){
00618 A[k*n+j]=A[k*n+j]*div;
00619 B[k*n+j]=B[k*n+j]*div;
00620 }
00621 for(i=0;i<n;i++){
00622 amult=A[i*n+k];
00623 if(i != k){
00624 for(j=0;j<n;j++){
00625 A[i*n+j]=A[i*n+j]-amult*A[k*n+j];
00626 B[i*n+j]=B[i*n+j]-amult*B[k*n+j];
00627 }
00628 }
00629 }
00630 }
00631 return TRUE;
00632 }
00633
00634 static void GetLengthAndAngles(void){
00635 int i;
00636 FILE *f;
00637 vector v,x={1.0,0.0,0.0};
00638 double dx,dy,l,angle;
00639 if(Nv < 2)return;
00640
00641 for(i=0;i<Nv-1;i++){
00642 dx=(double)(TVlist[i+1].x - TVlist[i].x);
00643 dy=(double)(TVlist[i+1].y - TVlist[i].y);
00644 TVlist[i].l=sqrt(dx*dx+dy*dy);
00645 TVlist[i].d[0]=dx/TVlist[i].l;
00646 TVlist[i].d[1]=dy/TVlist[i].l;
00647 TVlist[i].d[2]=0.0;
00648 if(i == 0)VECCOPY(x,v)
00649 else VECCOPY(TVlist[i-1].d,v)
00650 if(TwoCross(v,TVlist[i].d)){
00651 angle=acos(DOT(TVlist[i].d,v));
00652 if(angle < 0.0)angle=PI-angle;
00653 }
00654 else{
00655 angle=acos(DOT(TVlist[i].d,v));
00656 if(angle < 0.0)angle=PI+angle;
00657 else angle=2*PI-angle;
00658 }
00659 TVlist[i].theta=angle;
00660
00661 }
00662
00663 }
00664
00665 static BOOL TwoCross(vector last, vector next){
00666 vector r;
00667 CROSS(last,next,r)
00668 if(r[2] < 0.0)return FALSE;
00669 return TRUE;
00670 }
00671
00672 #if __WATCOMC__
00673 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00674 #else
00675 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00676 #endif
00677 switch (dwReason) {
00678 case DLL_PROCESS_ATTACH: {
00679 hThisInstance=hDLL;
00680 if(hDLL == NULL)MessageBox ( GetFocus()," NULL instance",NULL, MB_OK);
00681 break;
00682 }
00683 case DLL_PROCESS_DETACH:
00684 break;
00685 }
00686 return TRUE;
00687 }
00688
00689 #if __SC__
00690 #pragma startaddress(DllMain)
00691 #endif
00692
00693 BOOL _Xmodeler
00694 (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00695 lpEVI=lpevi;
00696 tracetool=0;
00697 hParent=parent_window;
00698 return Tester();
00699 }