trans_seq.c
Go to the documentation of this file.
1 #include "trans_seq.h"
2 
3 #include "geom.h"
4 #include "basic_algebra.h"
5 
6 #include <math.h>
7 #include <string.h>
8 
17 /*************************************************************************/
18 /*************************************************************************/
19 /*************************************************************************/
20 
22 {
23  t->t=CT_TRANS;
24  t->s=1;
25  t->u=NO_UINT;
26  t->v=NO_UINT;
27  NEW(t->ct,1,THTransform);
28  HTransformCopy(t->ct,ct);
29  t->vect=NULL;
30  t->p=NULL;
31 }
32 
33 void InitVarTrans(unsigned int tp,int s,unsigned int v,TTrans *t)
34 {
35  if ((tp==CT_TRANS)||(IS_PATCH_TRANS(tp))||(tp==TV))
36  Error("InitVarTrans should not be used for CT_TRANS, TV, or PA transforms");
37  t->t=tp;
38  t->s=s;
39  t->v=v;
40  t->u=NO_UINT;
41  t->ct=NULL;
42  t->vect=NULL;
43  t->p=NULL;
44 }
45 
46 void InitTVTrans(int s,unsigned int v,double *vect,TTrans *t)
47 {
48  t->t=TV;
49  t->s=s;
50  t->v=v;
51  t->u=NO_UINT;
52  t->ct=NULL;
53  NEW(t->vect,3,double);
54  memcpy(t->vect,vect,3*sizeof(double));
55  t->p=NULL;
56 }
57 
58 void InitPatchTrans(unsigned int tp,int s,unsigned int u,unsigned int v,
59  double **p,TTrans *t)
60 {
61  unsigned int i;
62 
63  if (!IS_PATCH_TRANS(tp))
64  Error("Using InitPatchTrans to define a non-PA transform");
65 
66  if (u==v)
67  Error("Repeated parameter in InitPatchTrans");
68 
69  t->t=tp;
70  t->s=s;
71  t->v=v;
72  t->u=u;
73  t->ct=NULL;
74  t->vect=NULL;
75  NEW(t->p,7,double*);
76  for(i=0;i<7;i++)
77  { NEW(t->p[i],3,double); }
78  if (tp==PA)
79  {
80  memcpy(t->p[0],p[0],3*sizeof(double)); /* (p_0) t->p_0=p_0 */
81  DifferenceVector(3,p[2],p[0],t->p[1]); /* (p_02) t->p_1=p_2-p_0 */
82  DifferenceVector(3,p[1],p[0],t->p[2]); /* (p_01) t->p_2=p_1-p_0 */
83  DifferenceVector(3,p[0],p[1],t->p[3]); /* (d) t->p_3=p_0-p_1-p_2+p_3 */
84  DifferenceVector(3,t->p[3],p[2],t->p[3]);
85  AccumulateVector(3,p[3],t->p[3]); /* t->p[3]+=p[3] */
86  }
87  else
88  {
89  /* For derived patches, we already have the four points computed */
90  for(i=0;i<4;i++)
91  memcpy(t->p[i],p[i],3*sizeof(double));
92  }
93 
94  CrossProduct(t->p[1],t->p[2],t->p[4]); /* (n0) t_p_4=p_0_2 x p_0_1 */
95  CrossProduct(t->p[1],t->p[3],t->p[5]); /* (n1) t_p_5=p_0_2 x d */
96  CrossProduct(t->p[3],t->p[2],t->p[6]); /* (n2) t_p_6=d x p_0_1 */
97 }
98 
99 void CopyTrans(TTrans *t_dst,TTrans *t_src)
100 {
101  unsigned int i;
102 
103  t_dst->t=t_src->t;
104  t_dst->s=t_src->s;
105  t_dst->v=t_src->v;
106  t_dst->u=t_src->u;
107  if (t_src->ct!=NULL)
108  {
109  NEW(t_dst->ct,1,THTransform);
110  HTransformCopy(t_dst->ct,t_src->ct);
111  }
112  else
113  t_dst->ct=NULL;
114 
115  if (t_src->vect!=NULL)
116  {
117  NEW(t_dst->vect,3,double);
118  memcpy(t_dst->vect,t_src->vect,3*sizeof(double));
119  }
120  else
121  t_dst->vect=NULL;
122 
123  if (t_src->p!=NULL)
124  {
125  NEW(t_dst->p,7,double*);
126  for(i=0;i<7;i++)
127  {
128  NEW(t_dst->p[i],3,double);
129  memcpy(t_dst->p[i],t_src->p[i],3*sizeof(double));
130  }
131  }
132  else
133  t_dst->p=NULL;
134 }
135 
137 {
138  CopyTrans(ti,t);
139  if (ti->t==CT_TRANS)
140  HTransformInverse(ti->ct,ti->ct);
141  else
142  ti->s=-ti->s;
143 }
144 
145 boolean TransHasVar(unsigned int v,TTrans *t)
146 {
147  return((v==t->v)||(v==t->u));
148 }
149 
150 void EvaluateVectorsPATrans(double u,double v,double *x,double *y,double *h,
151  TTrans *t)
152 {
153  if (!IS_PATCH_TRANS(t->t))
154  Error("Using EvaluatePATrans to evaluate a non-PA transform");
155 
156  /* x=n0+u*n1+v*n2 */
157  SumVectorScale(3,t->p[4],u,t->p[5],x);
158  SumVectorScale(3,x,v,t->p[6],x);
159 
160  /* y=p_02+v*d */
161  SumVectorScale(3,t->p[1],v,t->p[3],y);
162 
163  /* t=p_0+u*p_02+v*p_01+u*v*d */
164  SumVectorScale(3,t->p[0],u,t->p[1],h);
165  SumVectorScale(3,h,v,t->p[2],h);
166  SumVectorScale(3,h,u*v,t->p[3],h);
167 }
168 
169 void EvaluatePATrans(double u,double v,THTransform *a,TTrans *t)
170 {
171  double x[3],y[3],z[3],h[3];
172 
173  EvaluateVectorsPATrans(u,v,x,y,h,t);
174  Normalize(3,x);
175  Normalize(3,y);
176  /* z=x X y */
177  CrossProduct(x,y,z);
178 
179  HTransformFromVectors(x,y,z,h,a);
180  if (t->s<0)
181  HTransformInverse(a,a);
182 }
183 
185 {
186  if (t->ct!=NULL)
187  {
188  HTransformDelete(t->ct);
189  free(t->ct);
190  t->ct=NULL;
191  }
192  if (t->vect!=NULL)
193  {
194  free(t->vect);
195  t->vect=NULL;
196  }
197  if (t->p!=NULL)
198  {
199  unsigned int i;
200 
201  for(i=0;i<7;i++)
202  free(t->p[i]);
203  free(t->p);
204  t->p=NULL;
205  }
206 }
207 
208 
209 /*************************************************************************/
210 /*************************************************************************/
211 /*************************************************************************/
212 
214 {
215  ts->m=INIT_NUM_TERMS_TS;
216  ts->n=0;
217  NEW(ts->t,ts->m,TTrans*);
218 }
219 
220 void CopyTransSeq(TTransSeq *ts_dst,TTransSeq *ts_src)
221 {
222  unsigned int i;
223 
224  ts_dst->m=ts_src->m;
225  ts_dst->n=ts_src->n;
226 
227  NEW(ts_dst->t,ts_dst->m,TTrans *);
228  for(i=0;i<ts_dst->n;i++)
229  {
230  NEW(ts_dst->t[i],1,TTrans);
231  CopyTrans(ts_dst->t[i],ts_src->t[i]);
232  }
233 }
234 
236 {
237  unsigned int i;
238 
239  for(i=0;i<ts->n;i++)
240  {
241  DeleteTrans(ts->t[i]);
242  free(ts->t[i]);
243  }
244  ts->n=0;
245 }
246 
248 {
249  return(ts->n==0);
250 }
251 
253 {
254  unsigned int i;
255  boolean found;
256 
257  found=FALSE;
258  for(i=0;((!found)&&(i<ts->n));i++)
259  found=((ts->t[i]->t==CT_TRANS)&&(!HTransformIsTranslation(ts->t[i]->ct)));
260 
261  return(found);
262 }
263 
264 unsigned int TransSeqSize(TTransSeq *ts)
265 {
266  return(ts->n);
267 }
268 
270 {
271  if (i>=ts->n)
272  Error("Index out of range in GetVarElementFromTransSeq");
273 
274  return(ts->t[i]);
275 }
276 
278 {
279  /* For CT_TRANS we try to compact, if possible */
280  if (t->t==CT_TRANS)
281  {
282  if (t->s>0)
283  AddCtTrans2TransSeq(t->ct,ts);
284  else
285  {
286  THTransform ict;
287 
288  HTransformInverse(t->ct,&ict);
289  AddCtTrans2TransSeq(&ict,ts);
290  HTransformDelete(&ict);
291  }
292  }
293  else
294  {
295  /* For variable transforms compact only if the previous trasform is
296  the identity (this happens for just initialized transform sequences) */
297  if ((ts->n>0)&&(ts->t[ts->n-1]->t==CT_TRANS)&&(HTransformIsIdentity(ts->t[ts->n-1]->ct)))
298  {
299  DeleteTrans(ts->t[ts->n-1]);
300  CopyTrans(ts->t[ts->n-1],t);
301  }
302  else
303  {
304  if (ts->n==ts->m)
305  { MEM_DUP(ts->t,ts->m,TTrans *); }
306  NEW(ts->t[ts->n],1,TTrans);
307  CopyTrans(ts->t[ts->n],t);
308  ts->n++;
309  }
310  }
311 }
312 
314 {
315  if ((ts->n>0)&&(ts->t[ts->n-1]->t==CT_TRANS))
316  {
317  HTransformProduct(ts->t[ts->n-1]->ct,t,ts->t[ts->n-1]->ct);
318  /* Identity matrix is removed (execept the base one) */
319  if ((HTransformIsIdentity(ts->t[ts->n-1]->ct))&&(ts->n>1))
320  {
321  ts->n--;
322  DeleteTrans(ts->t[ts->n]);
323  free(ts->t[ts->n]);
324  }
325  }
326  else
327  {
328  if (ts->n==ts->m)
329  {
330  MEM_DUP(ts->t,ts->m,TTrans *);
331  }
332  NEW(ts->t[ts->n],1,TTrans);
333  InitCtTrans(t,ts->t[ts->n]);
334  ts->n++;
335  }
336 }
337 
338 void AddVarTrans2TransSeq(unsigned int t,int s,unsigned int v,TTransSeq *ts)
339 {
340  if (t==CT_TRANS)
341  Error("Adding a constant varaible transform in AddVarTrans2TransSeq");
342 
343  if (IS_PATCH_TRANS(t))
344  Error("Do not use AddVarTrans2TransSeq to add a patch transform to a Trans Seq");
345 
346  if (t==TV)
347  Error("Do not use AddVarTrans2TransSeq to add a displacement transform to a Trans Seq");
348 
349  if ((ts->n>0)&&(ts->t[ts->n-1]->t==CT_TRANS)&&(HTransformIsIdentity(ts->t[ts->n-1]->ct)))
350  InitVarTrans(t,s,v,ts->t[ts->n-1]);
351  else
352  {
353  if (ts->n==ts->m)
354  { MEM_DUP(ts->t,ts->m,TTrans *); }
355  NEW(ts->t[ts->n],1,TTrans);
356  InitVarTrans(t,s,v,ts->t[ts->n]);
357  ts->n++;
358  }
359 }
360 
361 void AddDispTrans2TransSeq(int s,unsigned int v,double *vect,TTransSeq *ts)
362 {
363  if ((ts->n>0)&&(ts->t[ts->n-1]->t==CT_TRANS)&&(HTransformIsIdentity(ts->t[ts->n-1]->ct)))
364  InitTVTrans(s,v,vect,ts->t[ts->n-1]);
365  else
366  {
367  if (ts->n==ts->m)
368  { MEM_DUP(ts->t,ts->m,TTrans *); }
369  NEW(ts->t[ts->n],1,TTrans);
370  InitTVTrans(s,v,vect,ts->t[ts->n]);
371  ts->n++;
372  }
373 }
374 
375 void AddPatchTrans2TransSeq(unsigned int t,int s,unsigned int u,unsigned int v,
376  double **p,TTransSeq *ts)
377 {
378  if ((ts->n>0)&&(ts->t[ts->n-1]->t==CT_TRANS)&&(HTransformIsIdentity(ts->t[ts->n-1]->ct)))
379  InitPatchTrans(t,s,u,v,p,ts->t[ts->n-1]);
380  else
381  {
382  if (ts->n==ts->m)
383  { MEM_DUP(ts->t,ts->m,TTrans *); }
384  NEW(ts->t[ts->n],1,TTrans);
385  InitPatchTrans(t,s,u,v,p,ts->t[ts->n]);
386  ts->n++;
387  }
388 }
389 
390 boolean VarIncludedinTransSeq(unsigned int v,TTransSeq *ts)
391 {
392  boolean found;
393  unsigned int i;
394 
395  found=FALSE;
396  i=0;
397  while ((!found)&&(i<ts->n))
398  {
399  found=TransHasVar(v,ts->t[i]);
400  i++;
401  }
402  return(found);
403 }
404 
405 void UpdateUsedDOF(unsigned int *dof,TTransSeq *ts)
406 {
407  unsigned int i;
408 
409  for(i=0;i<ts->n;i++)
410  {
411  switch (ts->t[i]->t)
412  {
413  case CT_TRANS:
414  break;
415  case TX:
416  dof[TX]++;
417  break;
418  case TY:
419  dof[TY]++;
420  break;
421  case TZ:
422  dof[TZ]++;
423  break;
424  case TV:
425  /* assuming a general displacement. */
426  dof[TX]++;
427  dof[TY]++;
428  dof[TZ]++;
429  break;
430  case PA:
431  case dPA_U:
432  case dPA_V:
433  case ddPA_UU:
434  case ddPA_UV:
435  case ddPA_VV:
436  /* Assuming a general patch */
437  dof[TX]++;
438  dof[TY]++;
439  dof[TZ]++;
440  dof[RX]++;
441  dof[RY]++;
442  dof[RZ]++;
443  break;
444  case RX:
445  case dRX:
446  case ddRX:
447  dof[RX]++;
448  break;
449  case RY:
450  case dRY:
451  case ddRY:
452  dof[RY]++;
453  break;
454  case RZ:
455  case dRZ:
456  case ddRZ:
457  dof[RZ]++;
458  break;
459  default:
460  Error("Unkown transform type in UpdateUsedDOF");
461  }
462  }
463 }
464 
465 void ShiftVariablesInTransSeq(unsigned int nv,TTransSeq *ts)
466 {
467  unsigned int i;
468 
469  for(i=0;i<ts->n;i++)
470  {
471  if (TransHasVar(nv,ts->t[i]))
472  Error("Removing a variable used in a transform sequence");
473  else
474  {
475  if ((ts->t[i]->v!=NO_UINT)&&(ts->t[i]->v>nv))
476  ts->t[i]->v--;
477  if ((ts->t[i]->u!=NO_UINT)&&(ts->t[i]->u>nv))
478  ts->t[i]->u--;
479  }
480  }
481 }
482 
484 {
485  if ((ts->n>2)&&(ts->t[0]->t==CT_TRANS)&&(ts->t[ts->n-1]->t==CT_TRANS))
486  {
487  ts->n--;
488  HTransformProduct(ts->t[ts->n]->ct,ts->t[0]->ct,ts->t[0]->ct);
489  DeleteTrans(ts->t[ts->n]);
490  free(ts->t[ts->n]);
491  }
492 }
493 
494 void DeriveTransSeq(unsigned int v,unsigned int *n,TTransSeq ***tsd,TTransSeq *ts)
495 {
496  unsigned int i;
497 
498  *n=0;
499  for(i=0;i<ts->n;i++)
500  {
501  if (TransHasVar(v,ts->t[i]))
502  (*n)++;
503  }
504 
505  /* *n will be typically 0 or 1 but it can be larger if a variable is repeated
506  in a loop equation. */
507  if (*n==0)
508  tsd=NULL;
509  else
510  {
511  THTransform a;
512  unsigned int r,t;
513  double sgn;
514 
515  NEW(*tsd,*n,TTransSeq*);
516  for(r=0;r<*n;r++)
517  {
518  /* We derive in turns for each time varible 'v' appears in the
519  sequence. '*n' is the maximum times and 'r' is the time with
520  respect to which we are deriving now. 't' is the numbers
521  of times the variable has been encounterd so far in the
522  scan over the sequence. */
523  t=0;
524  NEW((*tsd)[r],1,TTransSeq);
525  InitTransSeq((*tsd)[r]);
526  for(i=0;i<ts->n;i++)
527  {
528  if ((!TransHasVar(v,ts->t[i]))||(t!=r))
529  AddTrans2TransSeq(ts->t[i],(*tsd)[r]);
530  else
531  {
532  /* The r-th time variable 'v' appears in the sequence */
533  switch (ts->t[i]->t)
534  {
535  case TX:
536  HTransformZero(&a);
537  HTransformSetElement(AXIS_X,AXIS_H,(double)ts->t[i]->s,&a);
538  AddCtTrans2TransSeq(&a,(*tsd)[r]);
539  HTransformDelete(&a);
540  break;
541  case TY:
542  HTransformZero(&a);
543  HTransformSetElement(AXIS_Y,AXIS_H,(double)ts->t[i]->s,&a);
544  AddCtTrans2TransSeq(&a,(*tsd)[r]);
545  HTransformDelete(&a);
546  break;
547  case TZ:
548  HTransformZero(&a);
549  HTransformSetElement(AXIS_Z,AXIS_H,(double)ts->t[i]->s,&a);
550  AddCtTrans2TransSeq(&a,(*tsd)[r]);
551  HTransformDelete(&a);
552  break;
553  case TV:
554  sgn=(double)ts->t[i]->s;
555  HTransformZero(&a);
556  HTransformSetElement(AXIS_X,AXIS_H,sgn*ts->t[i]->vect[0],&a);
557  HTransformSetElement(AXIS_Y,AXIS_H,sgn*ts->t[i]->vect[1],&a);
558  HTransformSetElement(AXIS_Z,AXIS_H,sgn*ts->t[i]->vect[2],&a);
559  AddCtTrans2TransSeq(&a,(*tsd)[r]);
560  HTransformDelete(&a);
561  break;
562  case RX:
563  AddVarTrans2TransSeq(dRX,ts->t[i]->s,ts->t[i]->v,
564  (*tsd)[r]);
565  break;
566  case RY:
567  AddVarTrans2TransSeq(dRY,ts->t[i]->s,ts->t[i]->v,
568  (*tsd)[r]);
569  break;
570  case RZ:
571  AddVarTrans2TransSeq(dRZ,ts->t[i]->s,ts->t[i]->v,
572  (*tsd)[r]);
573  break;
574  case PA:
575  /* For parametrized transforms, we keep all the
576  information changing the type of transform */
577  if (v==ts->t[i]->u) /* Derivative w.r.t. the 1st param */
578  AddPatchTrans2TransSeq(dPA_U,ts->t[i]->s,ts->t[i]->u,
579  ts->t[i]->v,ts->t[i]->p,(*tsd)[r]);
580  else /* Derivative w.r.t. the 2nd param */
581  AddPatchTrans2TransSeq(dPA_V,ts->t[i]->s,ts->t[i]->u,
582  ts->t[i]->v,ts->t[i]->p,(*tsd)[r]);
583  break;
584  case dRX:
585  AddVarTrans2TransSeq(ddRX,ts->t[i]->s,
586  ts->t[i]->v,(*tsd)[r]);
587  break;
588  case dRY:
589  AddVarTrans2TransSeq(ddRY,ts->t[i]->s,
590  ts->t[i]->v,(*tsd)[r]);
591  break;
592  case dRZ:
593  AddVarTrans2TransSeq(ddRZ,ts->t[i]->s,
594  ts->t[i]->v,(*tsd)[r]);
595  break;
596  case dPA_U:
597  if (v==ts->t[i]->u) /* du du */
598  AddPatchTrans2TransSeq(ddPA_UU,ts->t[i]->s,ts->t[i]->u,
599  ts->t[i]->v,ts->t[i]->p,(*tsd)[r]);
600  else /* du dv */
601  AddPatchTrans2TransSeq(ddPA_UV,ts->t[i]->s,ts->t[i]->u,
602  ts->t[i]->v,ts->t[i]->p,(*tsd)[r]);
603  break;
604  case dPA_V:
605  if (v==ts->t[i]->u) /* dv du */
606  AddPatchTrans2TransSeq(ddPA_UV,ts->t[i]->s,ts->t[i]->u,
607  ts->t[i]->v,ts->t[i]->p,(*tsd)[r]);
608  else /* dv dv */
609  AddPatchTrans2TransSeq(ddPA_VV,ts->t[i]->s,ts->t[i]->u,
610  ts->t[i]->v,ts->t[i]->p,(*tsd)[r]);
611  break;
612  default:
613  Error("Unknown transform type in DeriveTransSeq");
614  }
615  }
616  if (TransHasVar(v,ts->t[i]))
617  t++;
618  }
619  }
620  }
621 }
622 
623 void EvaluateTransSeq(double *v,THTransform *r,TTransSeq *ts)
624 {
625  unsigned int i;
626  THTransform a;
627 
629  for(i=0;i<ts->n;i++)
630  {
631  if (ts->t[i]->t==CT_TRANS)
632  HTransformProduct(r,ts->t[i]->ct,r);
633  else
634  {
635  double val;
636  double d1,d2,d3;
637 
638  switch (ts->t[i]->t)
639  {
640  case TX:
641  d1=((double)(ts->t[i]->s))*v[ts->t[i]->v];
642  HTransformAcumTrans(d1,0,0,r);
643  break;
644  case TY:
645  d1=((double)(ts->t[i]->s))*v[ts->t[i]->v];
646  HTransformAcumTrans(0,d1,0,r);
647  break;
648  case TZ:
649  d1=((double)(ts->t[i]->s))*v[ts->t[i]->v];
650  HTransformAcumTrans(0,0,d1,r);
651  break;
652  case TV:
653  val=((double)(ts->t[i]->s))*v[ts->t[i]->v];
654  d1=ts->t[i]->vect[0];
655  d2=ts->t[i]->vect[1];
656  d3=ts->t[i]->vect[2];
657  HTransformAcumTrans(val*d1,val*d2,val*d3,r);
658  break;
659  case RX:
660  val=((double)(ts->t[i]->s))*v[ts->t[i]->v];
661  HTransformAcumRot(RX,sin(val),cos(val),r);
662  break;
663  case RY:
664  val=((double)(ts->t[i]->s))*v[ts->t[i]->v];
665  HTransformAcumRot(RY,sin(val),cos(val),r);
666  break;
667  case RZ:
668  val=((double)(ts->t[i]->s))*v[ts->t[i]->v];
669  HTransformAcumRot(RZ,sin(val),cos(val),r);
670  break;
671  case PA:
672  EvaluatePATrans(v[ts->t[i]->u],v[ts->t[i]->v],&a,ts->t[i]);
673  HTransformProduct(r,&a,r);
674  HTransformDelete(&a);
675  break;
676  case dRX:
677  /* With negative sign we have to evaluate the derivative of the
678  inverse. However, for rotations this derivative can be
679  computed directly. */
680  val=v[ts->t[i]->v];
681  HTransformRx2(((double)(ts->t[i]->s))*cos(val),-sin(val),&a);
684  HTransformProduct(r,&a,r);
685  HTransformDelete(&a);
686  break;
687  case dRY:
688  val=v[ts->t[i]->v];
689  HTransformRy2(((double)(ts->t[i]->s))*cos(val),-sin(val),&a);
692  HTransformProduct(r,&a,r);
693  HTransformDelete(&a);
694  break;
695  case dRZ:
696  val=v[ts->t[i]->v];
697  HTransformRz2(((double)(ts->t[i]->s))*cos(val),-sin(val),&a);
700  HTransformProduct(r,&a,r);
701  HTransformDelete(&a);
702  break;
703  case dPA_U:
704  {
705  double v1,v2;
706  double nv[3],dnv[3],nx,ny;
707  double x[3],y[3],t[3];
708  double dx[3],dy[3]={0,0,0},dz[3];
709 
710  v1=v[ts->t[i]->u];
711  v2=v[ts->t[i]->v];
712 
713  /* Get the non-normalized x,y,t vectors (t is not used) */
714  EvaluateVectorsPATrans(v1,v2,x,y,t,ts->t[i]);
715 
716  /* dx = diff(x_normalized,u) */
717  /* x_norm x = norm(x)
718  For a generic vector'v' depending on a parameter 'u',
719  and with n_v=norm(v) (i.e., n_f is also funciton of 'u')
720  diff(v/n_v,u)=(1/n_v^2)*[diff(v,u)*n_v-v*diff(n_v,u)]
721  where
722  diff(n_v,u)=1/n_v*diff(v\tr*v,u)
723  =1/n_v*v\tr*diff(v,u)
724  and, thus
725  diff(v/n_v,u)= (1/n_v^2)*[diff(v,u)*n_v
726  -v*1/n_v*v\tr*diff(v,u)]
727  = diff(v,u)/n_v
728  -(v/n_v)*(v\tr/n_v)*(diff(v,u)/n_v)
729 
730  Thus, if v_norm=v/nv and dv_norm=diff(v,u)/norm(v)
731  then diff(v/n_v,u)=dv_norm-(v_norm\tr*dv_norm)*v_norm
732 
733  This is used every time we have to evaluate the
734  differential of a normalized vector w.r.t. a given variable
735  where we have the formula giving the unormalized vector.
736  */
737  nx=Norm(3,x);
738  ScaleVector2(1/nx,3,x,nv);
739  /* ts->t[i]->p[5] = n1 = diff(x,u) */
740  ScaleVector2(1/nx,3,ts->t[i]->p[5],dnv);
741  SumVectorScale(3,dnv,-DotProduct(nv,dnv),nv,dx);
742 
743  /* dy = diff(y_norm,u) is zero */
744 
745  /* dz = diff(z_norm,u) with z_norm = x_norm X y_norm */
746  ny=Norm(3,y);
747  CrossProduct(dx,y,dz);
748  ScaleVector2(1/ny,3,dz,dz);
749 
750  /* dt = diff(p,u) = p_02+v*d = y */
751 
752  /* Set up the matrix */
753  if (ts->t[i]->s>0)
754  {
755  HTransformFromVectors(dx,dy,dz,y,&a);
757  }
758  else
759  {
760  /* trans=T*R -> trans\inv=R\tr*(-T)=[R\tr -R\tr*t]
761  diff(trans\inv)=[diff(R\tr) -[diff(R\tr)*t+R\tr*diff(t)]]
762  */
763  THTransform Rt,dR;
764  double h[3],z[3],y1[3];
765  double zero[3]={0,0,0};
766 
767  /* R\tr */
768  ScaleVector2(1/nx,3,x,x);
769  ScaleVector2(1/ny,3,y,y1);
770  CrossProduct(x,y1,z);
771  HTransformFromVectors(x,y1,z,zero,&Rt);
772  HTransformTranspose(&Rt,&Rt);
773 
774  /* a=diff(R\tr) = diff(R)\tr*/
775  HTransformFromVectors(dx,dy,dz,zero,&dR);
777  HTransformTranspose(&dR,&a);
778 
779  /* Now set the homogeneous part of 'a' */
780  HTransformApplyRot(t,h,&a); /* h=diff(R\tr)*t */
781  HTransformApplyRot(y,z,&Rt); /* z=R\tr*diff(t) */
782  AccumulateVector(3,z,h); /* h=h+z */
783 
787  }
788  HTransformProduct(r,&a,r);
789  HTransformDelete(&a);
790  }
791  break;
792  case dPA_V:
793  {
794  double v1,v2;
795  double nv[3],dnv[3],nx,ny;
796  double x[3],y[3],t[3];
797  double dx[3],dy[3],dz[3],dt[3];
798 
799  v1=v[ts->t[i]->u];
800  v2=v[ts->t[i]->v];
801 
802  /* Get the non-normalized x,y,t vectors (only x and y are used) */
803  EvaluateVectorsPATrans(v1,v2,x,y,t,ts->t[i]);
804 
805  /* dx = diff(x_normalized,v) */
806  nx=Norm(3,x);
807  ScaleVector2(1/nx,3,x,nv);
808  /* ts->t[i]->p[6] = n2 = diff(x,v) */
809  ScaleVector2(1/nx,3,ts->t[i]->p[6],dnv);
810  SumVectorScale(3,dnv,-DotProduct(nv,dnv),nv,dx);
811 
812  /* dy = diff(y_normalized,v) */
813  ny=Norm(3,y);
814  ScaleVector2(1/ny,3,y,nv);
815  /* ts->t[i]->p[3] = d = diff(y,v) */
816  ScaleVector2(1/ny,3,ts->t[i]->p[3],dnv);
817  SumVectorScale(3,dnv,-DotProduct(nv,dnv),nv,dy);
818 
819  /* dz = diff(z_norm,u) with z_norm = x_norm X y_norm */
820  /* diff(z_norm,v) = diff(x_norm,v) X y/norm(y)
821  + x/norm(x) X diff(y_norm,v) */
822  CrossProduct(dx,y,dz);
823  ScaleVector2(1/ny,3,dz,dz);
824  CrossProduct(x,dy,nv);
825  SumVectorScale(3,dz,1/nx,nv,dz);
826 
827  /* dt = diff(t,v) = p_01+u*d */
828  SumVectorScale(3,ts->t[i]->p[2],v1,ts->t[i]->p[3],dt);
829 
830  if (ts->t[i]->s>0)
831  {
832  /* Set up the matrix */
833  HTransformFromVectors(dx,dy,dz,dt,&a);
835  }
836  else
837  {
838  /* trans=T*R -> trans\inv=R\tr*(-T)=[R\tr -R\tr*t]
839  diff(trans\inv)=[diff(R\tr) -[diff(R\tr)*t+R\tr*diff(t)]]
840  */
841  THTransform Rt,dR;
842  double h[3],z[3];
843  double zero[3]={0,0,0};
844 
845  /* R\tr */
846  ScaleVector2(1/nx,3,x,x);
847  ScaleVector2(1/ny,3,y,y);
848  CrossProduct(x,y,z);
849  HTransformFromVectors(x,y,z,zero,&Rt);
850  HTransformTranspose(&Rt,&Rt);
851 
852  /* a=diff(R\tr) = diff(R)\tr*/
853  HTransformFromVectors(dx,dy,dz,zero,&dR);
855  HTransformTranspose(&dR,&a);
856 
857  /* Now set the homogeneous part of 'a' */
858  HTransformApplyRot(t,h,&a); /* h=diff(R\tr)*t */
859  HTransformApplyRot(dt,z,&Rt); /* z=R\tr*diff(t) */
860  AccumulateVector(3,z,h); /* h=h+z */
861 
865  }
866  HTransformProduct(r,&a,r);
867  HTransformDelete(&a);
868  }
869  break;
870  case ddRX:
871  /* With negative sign we have to evaluate the second derivative of the
872  inverse. However, for rotations this derivative can be
873  computed directly. */
874  val=v[ts->t[i]->v];
875  HTransformRx2(-((double)(ts->t[i]->s))*sin(val),-cos(val),&a);
878  HTransformProduct(r,&a,r);
879  HTransformDelete(&a);
880  break;
881  case ddRY:
882  val=v[ts->t[i]->v];
883  HTransformRy2(-((double)(ts->t[i]->s))*sin(val),-cos(val),&a);
886  HTransformProduct(r,&a,r);
887  HTransformDelete(&a);
888  break;
889  case ddRZ:
890  val=v[ts->t[i]->v];
891  HTransformRz2(-((double)(ts->t[i]->s))*sin(val),-cos(val),&a);
894  HTransformProduct(r,&a,r);
895  HTransformDelete(&a);
896  break;
897  case ddPA_UU:
898  case ddPA_UV:
899  case ddPA_VV:
900  Error("The evaluation of the second derivative of parametrized-patch transforms is not implemented yet");
901  break;
902  default:
903  Error("Unknown transform type in EvaluateTransSeq");
904  }
905  }
906  }
907 }
908 
909 void PrintTransSeq(FILE *f,char **varNames,TTransSeq *ts)
910 {
911  unsigned int i,j,k,t;
912  double val;
913 
914  for(i=0;i<ts->n;i++)
915  {
916  t=ts->t[i]->t;
917  if (t==CT_TRANS)
918  {
919  if (HTransformIsIdentity(ts->t[i]->ct))
920  fprintf(f,"Id");
921  else
922  {
923  //HTransformPrettyPrint(f,ts->t[i]->ct);
924 
925  fprintf(f,"T(");
926  for(j=0;j<DIM_SP;j++)
927  {
928  for(k=0;k<(DIM_SP+1);k++)
929  {
930  val=HTransformGetElement(j,k,ts->t[i]->ct);
931  PrintReal(f,val);
932  if (k<DIM_SP)
933  fprintf(f,",");
934  }
935  if (j<DIM_SP-1)
936  fprintf(f,";");
937  }
938  fprintf(f,")");
939  }
940  }
941  else
942  {
943  switch (t)
944  {
945  case TX:
946  fprintf(f,"Tx(");
947  break;
948  case TY:
949  fprintf(f,"Ty(");
950  break;
951  case TZ:
952  fprintf(f,"Tz(");
953  break;
954  case TV:
955  fprintf(f,"Tv(");
956  PrintReal(f,ts->t[i]->vect[0]);fprintf(f,",");
957  PrintReal(f,ts->t[i]->vect[1]);fprintf(f,",");
958  PrintReal(f,ts->t[i]->vect[2]);fprintf(f,",");
959  break;
960  case RX:
961  fprintf(f,"Rx(");
962  break;
963  case RY:
964  fprintf(f,"Ry(");
965  break;
966  case RZ:
967  fprintf(f,"Rz(");
968  break;
969  case PA:
970  case dPA_U:
971  case dPA_V:
972  case ddPA_UU:
973  case ddPA_UV:
974  case ddPA_VV:
975  {
976  unsigned int k;
977  double v[3];
978 
979  switch (t)
980  {
981  case PA:
982  fprintf(f,"Pa(");
983  break;
984  case dPA_U:
985  fprintf(f,"dPa_u(");
986  break;
987  case dPA_V:
988  fprintf(f,"dPa_v(");
989  break;
990  case ddPA_UU:
991  fprintf(f,"ddPa_uu(");
992  break;
993  case ddPA_UV:
994  fprintf(f,"ddPa_uv(");
995  break;
996  case ddPA_VV:
997  fprintf(f,"ddPa_vv(");
998  break;
999  }
1000  /* Print the 4 vectors defining the patch */
1001  if (t!=PA)
1002  {
1003  /* For derived patches we print the already
1004  processed patch extremes +
1005  Derived patches typically do not appear in
1006  equation files */
1007  for(j=0;j<4;j++)
1008  {
1009  for(k=0;k<3;k++)
1010  {
1011  PrintReal(f,ts->t[i]->p[j][k]);
1012  if (k<2) fprintf(f,",");
1013  }
1014  fprintf(f,";");
1015  }
1016  }
1017  else
1018  {
1019  /* For oritinal patches we print the
1020  orignal extremes. This facilitates the
1021  unsderstanding of equation files. */
1022  /* p_0 */
1023  for(k=0;k<3;k++)
1024  {
1025  PrintReal(f,ts->t[i]->p[0][k]);
1026  if (k<2) fprintf(f,",");
1027  }
1028  fprintf(f,";");
1029  /* p_1=p_01+p_0 */
1030  SumVector(3,ts->t[i]->p[2],ts->t[i]->p[0],v);
1031  for(k=0;k<3;k++)
1032  {
1033  PrintReal(f,v[k]);
1034  if (k<2) fprintf(f,",");
1035  }
1036  fprintf(f,";");
1037  /* p_2=p_02+p_0 */
1038  SumVector(3,ts->t[i]->p[1],ts->t[i]->p[0],v);
1039  for(k=0;k<3;k++)
1040  {
1041  PrintReal(f,v[k]);
1042  if (k<2) fprintf(f,",");
1043  }
1044  }
1045  fprintf(f,";");
1046  /* p_3=d+p_01+p_02+p_0 */
1047  SumVector(3,ts->t[i]->p[3],ts->t[i]->p[2],v);
1048  AccumulateVector(3,ts->t[i]->p[1],v);
1049  AccumulateVector(3,ts->t[i]->p[0],v);
1050  for(k=0;k<3;k++)
1051  {
1052  PrintReal(f,v[k]);
1053  if (k<2) fprintf(f,",");
1054  }
1055  fprintf(f,";");
1056 
1057  /* Now the variables */
1058  if (varNames!=NULL)
1059  {
1060  char *n;
1061 
1062  n=varNames[ts->t[i]->u];
1063  PRINT_VARIABLE_NAME(f,n);
1064  }
1065  else
1066  fprintf(f,"v_%u",ts->t[i]->u);
1067  fprintf(f,",");
1068  }
1069  break;
1070  case dRX:
1071  fprintf(f,"dRx(");
1072  break;
1073  case dRY:
1074  fprintf(f,"dRy(");
1075  break;
1076  case dRZ:
1077  fprintf(f,"dRz(");
1078  break;
1079  case ddRX:
1080  fprintf(f,"ddRx(");
1081  break;
1082  case ddRY:
1083  fprintf(f,"ddRy(");
1084  break;
1085  case ddRZ:
1086  fprintf(f,"ddRz(");
1087  break;
1088  default:
1089  Error("Unknown transform type in EvaluateTransSeq");
1090  }
1091  if (varNames!=NULL)
1092  {
1093  char *n;
1094 
1095  n=varNames[ts->t[i]->v];
1096  PRINT_VARIABLE_NAME(f,n);
1097  }
1098  else
1099  fprintf(f,"v_%u",ts->t[i]->v);
1100  fprintf(f,")");
1101  if (ts->t[i]->s<0)
1102  fprintf(f,"^-1");
1103  }
1104  if (i<(ts->n-1))
1105  fprintf(f,"*");
1106  }
1107 }
1108 
1110 {
1111  ResetTransSeq(ts);
1112  free(ts->t);
1113 }
void UpdateUsedDOF(unsigned int *dof, TTransSeq *ts)
Determines the dof used in a transform sequence.
Definition: trans_seq.c:405
#define AXIS_X
One of the dimension of R^3.
Definition: htransform.h:83
Definition of basic functions.
void HTransformRz2(double s, double c, THTransform *t)
Constructor.
Definition: htransform.c:226
#define FALSE
FALSE.
Definition: boolean.h:30
boolean VarIncludedinTransSeq(unsigned int v, TTransSeq *ts)
Determines if the sequence includes a given variable.
Definition: trans_seq.c:390
#define dPA_V
Derivative of a PA transform.
Definition: trans_seq.h:70
boolean TransHasVar(unsigned int v, TTrans *t)
Identifies if a variable is involved in a given transform.
Definition: trans_seq.c:145
#define ddPA_VV
Double derivative of a PA transform.
Definition: trans_seq.h:109
#define NEW(_var, _n, _type)
Allocates memory space.
Definition: defines.h:385
#define ddRX
Double derivative of a Rx transform.
Definition: trans_seq.h:76
void HTransformTranspose(THTransform *t, THTransform *tt)
Transpose of a homogeneous transform.
Definition: htransform.c:618
A homgeneous transform in R^3.
unsigned int v
Definition: trans_seq.h:139
#define AXIS_Y
One of the dimension of R^3.
Definition: htransform.h:91
#define RZ
One of the types of homogeneous transforms in R^3.
Definition: htransform.h:75
void HTransformZero(THTransform *t)
Constructor.
Definition: htransform.c:75
CBLAS_INLINE double Norm(unsigned int s, double *v)
Computes the norm of a vector.
CBLAS_INLINE void SumVector(unsigned int s, double *v1, double *v2, double *v)
Adds two vectors.
Definition: basic_algebra.c:67
void HTransformApplyRot(double *p_in, double *p_out, THTransform *t)
Multiply the rotation part of the homogeneous transform and a vector.
Definition: htransform.c:747
void TransInvert(TTrans *ti, TTrans *t)
Invert a transform.
Definition: trans_seq.c:136
void CopyTransSeq(TTransSeq *ts_dst, TTransSeq *ts_src)
Constructor.
Definition: trans_seq.c:220
#define INIT_NUM_TERMS_TS
Initial room for terms in a transform sequence.
Definition: trans_seq.h:117
CBLAS_INLINE void AccumulateVector(unsigned int s, double *v1, double *v2)
Adds a vector to another vectors.
Definition: basic_algebra.c:55
void AddVarTrans2TransSeq(unsigned int t, int s, unsigned int v, TTransSeq *ts)
Adds a variable transform to the sequence.
Definition: trans_seq.c:338
void EvaluatePATrans(double u, double v, THTransform *a, TTrans *t)
Evaluates a PA transform.
Definition: trans_seq.c:169
CBLAS_INLINE void HTransformAcumTrans(double tx, double ty, double tz, THTransform *t)
Computes the result of multiplying a homogeneous transform by a translation matrix with parameters tx...
Definition: htransform.c:641
#define dRX
Derivative of a Rx transform.
Definition: trans_seq.h:44
#define RY
One of the types of homogeneous transforms in R^3.
Definition: htransform.h:67
CBLAS_INLINE void Normalize(unsigned int s, double *v)
Normalizes a vector.
void ResetTransSeq(TTransSeq *ts)
Semi-destructor.
Definition: trans_seq.c:235
void Error(const char *s)
General error function.
Definition: error.c:80
#define TZ
One of the types of homogeneous transforms in R^3.
Definition: htransform.h:51
#define AXIS_H
The homogeneous dimension in R^3.
Definition: htransform.h:108
CBLAS_INLINE void HTransformProduct(THTransform *t1, THTransform *t2, THTransform *t3)
Product of two homogeneous transforms.
Definition: htransform.c:404
void InitPatchTrans(unsigned int tp, int s, unsigned int u, unsigned int v, double **p, TTrans *t)
Initializes a parametrized-patch transform.
Definition: trans_seq.c:58
#define ddPA_UU
Double derivative of a PA transform.
Definition: trans_seq.h:95
Sequence (product) of homogeneous transforms.
void DeleteTrans(TTrans *t)
Destructor.
Definition: trans_seq.c:184
boolean HTransformIsTranslation(THTransform *t)
Identify the translation matrices.
Definition: htransform.c:96
double HTransformGetElement(unsigned int i, unsigned int j, THTransform *t)
Gets an element in a homogeneous transform.
Definition: htransform.c:323
void HTransformFromVectors(double *x, double *y, double *z, double *h, THTransform *t)
Defines a homogeneous transform from 4 vectors.
Definition: htransform.c:335
#define ddRZ
Double derivative of a Rx transform.
Definition: trans_seq.h:88
void AddCtTrans2TransSeq(THTransform *t, TTransSeq *ts)
Adds a constant transform to the sequence.
Definition: trans_seq.c:313
double DotProduct(double *v1, double *v2)
Computes the dot product of two 3d vectors.
Definition: geom.c:643
void HTransformInverse(THTransform *t, THTransform *ti)
Inverse of a homogeneous transform.
Definition: htransform.c:468
CBLAS_INLINE void ScaleVector2(double f, unsigned int s, double *v, double *vout)
Scales a vector.
Definition: basic_algebra.c:42
unsigned int TransSeqSize(TTransSeq *ts)
Number of elements in the transform sequence.
Definition: trans_seq.c:264
#define AXIS_Z
One of the dimension of R^3.
Definition: htransform.h:99
#define TX
One of the types of homogeneous transforms in R^3.
Definition: htransform.h:35
#define PRINT_VARIABLE_NAME(f, name)
Prints a variable name into a file.
Definition: defines.h:427
A step in a transform sequence.
Definition: trans_seq.h:136
THTransform * ct
Definition: trans_seq.h:143
void CopyTrans(TTrans *t_dst, TTrans *t_src)
Constructor.
Definition: trans_seq.c:99
void DifferenceVector(unsigned int s, double *v1, double *v2, double *v)
Substracts two vectors.
double * vect
Definition: trans_seq.h:145
void AddTrans2TransSeq(TTrans *t, TTransSeq *ts)
Adds a transform to a transform sequence.
Definition: trans_seq.c:277
unsigned int n
Definition: trans_seq.h:298
void DeriveTransSeq(unsigned int v, unsigned int *n, TTransSeq ***tsd, TTransSeq *ts)
Derive a sequence of transforms.
Definition: trans_seq.c:494
#define dPA_U
Derivative of a PA transform.
Definition: trans_seq.h:63
A sequence of transforms.
Definition: trans_seq.h:296
TTrans ** t
Definition: trans_seq.h:299
void PrintReal(FILE *f, double r)
Pretty print a real number.
Definition: geom.c:736
CBLAS_INLINE void HTransformAcumRot(unsigned int type, double s, double c, THTransform *t)
Computes the result of multiplying a homogeneous transform by a rotation matrix.
Definition: htransform.c:673
#define ddRY
Double derivative of a Rx transform.
Definition: trans_seq.h:82
void EvaluateTransSeq(double *v, THTransform *r, TTransSeq *ts)
Evaluates the transform sequence.
Definition: trans_seq.c:623
#define dRZ
Derivative of a Rz transform.
Definition: trans_seq.h:56
void DeleteTransSeq(TTransSeq *ts)
Destructor.
Definition: trans_seq.c:1109
boolean HasCtRotTransSeq(TTransSeq *ts)
Checks if the tranform sequence includes contant rotations.
Definition: trans_seq.c:252
void InitCtTrans(THTransform *ct, TTrans *t)
Initializes a constant transform.
Definition: trans_seq.c:21
#define MEM_DUP(_var, _n, _type)
Duplicates a previously allocated memory space.
Definition: defines.h:414
unsigned int t
Definition: trans_seq.h:137
#define NO_UINT
Used to denote an identifier that has not been initialized.
Definition: defines.h:435
CBLAS_INLINE void SumVectorScale(unsigned int s, double *v1, double w, double *v2, double *v)
Adds two vectors with a scale.
Definition: basic_algebra.c:86
#define RX
One of the types of homogeneous transforms in R^3.
Definition: htransform.h:59
#define dRY
Derivative of a Ry transform.
Definition: trans_seq.h:50
void AddDispTrans2TransSeq(int s, unsigned int v, double *vect, TTransSeq *ts)
Adds a displacement transform to the sequence.
Definition: trans_seq.c:361
#define IS_PATCH_TRANS(t)
Checks if a transform is a parametrized patch (or derived).
Definition: trans_seq.h:126
void EvaluateVectorsPATrans(double u, double v, double *x, double *y, double *h, TTrans *t)
Computes the vectors defining a PA transform.
Definition: trans_seq.c:150
void ShiftVariablesInTransSeq(unsigned int nv, TTransSeq *ts)
Adjust variable indices after removing a variable.
Definition: trans_seq.c:465
void HTransformDelete(THTransform *t)
Destructor.
Definition: htransform.c:833
int s
Definition: trans_seq.h:141
#define PA
Point on a patch.
Definition: trans_seq.h:31
void InitTVTrans(int s, unsigned int v, double *vect, TTrans *t)
Initializes a TV transform.
Definition: trans_seq.c:46
#define ddPA_UV
Double derivative of a PA transform.
Definition: trans_seq.h:102
TTrans * GetElementFromTransSeq(unsigned int i, TTransSeq *ts)
Returns an element from a transform sequence.
Definition: trans_seq.c:269
void HTransformSetElement(unsigned int i, unsigned int j, double v, THTransform *t)
Sets an element in a homogeneous transform.
Definition: htransform.c:306
void PrintTransSeq(FILE *f, char **varNames, TTransSeq *ts)
Prints a transform sequence to a file.
Definition: trans_seq.c:909
#define DIM_SP
Dimensions of R^3.
Definition: htransform.h:27
void HTransformCopy(THTransform *t_dst, THTransform *t_src)
Copy constructor.
Definition: htransform.c:83
#define TV
Displacement along a vector.
Definition: trans_seq.h:24
boolean IsEmptyTransSeq(TTransSeq *ts)
Identify empty transform sequences.
Definition: trans_seq.c:247
void InitTransSeq(TTransSeq *ts)
Constructor.
Definition: trans_seq.c:213
#define CT_TRANS
Constant transform.
Definition: trans_seq.h:38
void HTransformIdentity(THTransform *t)
Constructor.
Definition: htransform.c:69
unsigned int m
Definition: trans_seq.h:297
void CrossProduct(double *v1, double *v2, double *v3)
Computes the cross product of two 3d vectors.
Definition: geom.c:630
void HTransformRy2(double s, double c, THTransform *t)
Constructor.
Definition: htransform.c:216
void AddPatchTrans2TransSeq(unsigned int t, int s, unsigned int u, unsigned int v, double **p, TTransSeq *ts)
Adds a Parametrized-Patch transform to a transform sequence.
Definition: trans_seq.c:375
void InitVarTrans(unsigned int tp, int s, unsigned int v, TTrans *t)
Initializes a variable transform.
Definition: trans_seq.c:33
double ** p
Definition: trans_seq.h:146
void HTransformRx2(double s, double c, THTransform *t)
Constructor.
Definition: htransform.c:206
void SimplifyTransSeq(TTransSeq *ts)
Reduces the complexity of the tranform sequence.
Definition: trans_seq.c:483
#define TY
One of the types of homogeneous transforms in R^3.
Definition: htransform.h:43
unsigned int u
Definition: trans_seq.h:138
boolean HTransformIsIdentity(THTransform *t)
Identify the identity matrix.
Definition: htransform.c:91