IK2D.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 -  OpenFX Development Team
00004 
00005 This program is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 You may contact the OpenFX development team via elecronic mail
00020 at core@openfx.org, or visit our website at http://openfx.org for
00021 further information and support details.
00022 -- */
00023 
00024 /*  IK2D.C                                                            */
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){ /* add */
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){ /* move */
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]; //target
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){/*MessageBox(NULL,"Out of iteration",NULL,MB_OK);*/ break;}
00402    CalculateJacobian(J,Nv1);
00403 //J[3]=0.0;      // Lock
00404 //J[Nv1+3]=0.0;  // Lock
00405 //J[5]=0.0;      // Lock
00406 //J[Nv1+5]=0.0;  // Lock
00407 //for(i=0;i<Nv1;i++){
00408 //J[i] *= (1.0+2.0*(double)(i)); // damping
00409 //J[Nv1+i] *= (1.0+2.0*(double)(i)); // damping
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;                             // can't reach desired point
00418      }
00419      else{
00420        MultiplyMatrix(Ji,Nv1,2,dx,2,1,dTheta);
00421 
00422 //for(i=0;i<Nv1;i++)dTheta[i] *= 1.0/(1.0+5.0*(double)(Nv1-1-i)); // damping old
00423 //dTheta[2]=0.0; locking old
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;   // converged to solution
00445      }
00446    }
00447    else{
00448      MessageBeep(MB_OK);
00449    }
00450  }
00451  //
00452  // get new positions from the Theta
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  // TVlist[Lv].x += xi; TVlist[Lv].y += yi;
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;                       // M  is "n" rows "m" columns  [n x m]
00543  for(i=0;i<n;i++){
00544    for(j=0;j<m;j++){
00545      *(Mt+j*n+i) = *(M+i*m+j);   // 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;           // [n1 x m2][n2 x m2] result is [n1 x m2]
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        //  s += M1[i*m1+k]*M2[k*m2+j];  //  M1[i][k] * M2[k][j]
00563      }
00564      *(I+i*m2+j) = s;                   //  I[i*m2+j]=s;   // I[i][j]
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  //f=fopen("f:\\debug","w");
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    //fprintf(f,"Link %ld angle %lf\n",i,angle/PI*180.0);
00661  }
00662  //fclose(f);
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 }

Generated on Sun Apr 27 14:20:11 2014 for OpenFX by  doxygen 1.5.6