HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EUC_Expression.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  * Defines the expressions that can be performed on sets of
27  * euclidean objects.
28  */
29 
30 #include "EUC_Expression.h"
31 
32 #include <SYS/SYS_Math.h>
33 #include <UT/UT_Vector3.h>
34 #include <UT/UT_RootFinder.h>
35 
36 using namespace HDK_Sample;
37 
38 EUC_ExpressionList EUC_Expression::ourExpressionList;
39 int EUC_Expression::ourEvaluateTime = 0;
40 
41 //
42 // EUC_Expression
43 //
45 {
46  myRefCount = 0;
47  myUid = ourExpressionList.size();
48  myLastEvaluateTime = 0;
49  myCd = 1;
50  myVisible = true;
51  ourExpressionList.append(this);
52 }
53 
55 {
56  // Eliminate ourselves from the expression list.
57  ourExpressionList(getUid()) = 0;
58 }
59 
60 void
62 {
63  myRefCount++;
64 }
65 
66 void
68 {
69  myRefCount--;
70  if (myRefCount <= 0)
71  delete this;
72 }
73 
76 {
77  // Out of bound is not created.
78  if (uid < 0 || uid >= ourExpressionList.size())
79  return 0;
80 
81  return ourExpressionList(uid);
82 }
83 
84 void
85 EUC_Expression::setLook(bool visible, const UT_Vector3 &cd)
86 {
87  myVisible = visible;
88  myCd = cd;
89 }
90 
91 void
93 {
94  obj->setLook(myVisible, myCd);
95 }
96 
97 void
99 {
100  // Reset the global evaluate time so we clear all the caches.
101  ourEvaluateTime++;
102 
103  // Call the recursive evaluate. User wants total number of objects.
104  EUC_ObjectList tmp;
105 
106  evaluateRecurse(tmp, results);
107 }
108 
109 void
111  EUC_ObjectList &totalobj)
112 {
113  // Check to see if we are already cached.
114  if (myLastEvaluateTime == ourEvaluateTime)
115  {
116  result = myObjectCache;
117  return;
118  }
119  // Call subclass & cache.
120  myLastEvaluateTime = ourEvaluateTime;
121  myObjectCache.setSize(0);
122  evaluateSubclass(myObjectCache, totalobj);
123  result = myObjectCache;
124 }
125 
126 //
127 // EUC_ExprPoint
128 //
130 {
131  myPos = pos;
132 }
133 
134 void
136  EUC_ObjectList &totalobj)
137 {
138  EUC_Point *pt;
139 
140  pt = new EUC_Point(myPos);
141  applyLook(pt);
142  result.setSize(0);
143  result.append(pt);
144  totalobj.append(pt);
145 }
146 
147 //
148 // EUC_ExprPointFromObject
149 //
151 {
152  src->addRef();
153  mySource = src;
154  myIndex = idx;
155 }
156 
158 {
159  mySource->removeRef();
160 }
161 
162 void
164  EUC_ObjectList &totalobj)
165 {
166  EUC_Point *pt;
167  EUC_ObjectList objlist;
168  EUC_Object *obj;
169  int i, n;
170  UT_Vector2 pos;
171  bool haspos;
172 
173  result.setSize(0);
174  mySource->evaluateRecurse(objlist, totalobj);
175  n = objlist.size();
176  for (i = 0; i < n; i++)
177  {
178  obj = objlist(i);
179  haspos = false;
180  switch (obj->getType())
181  {
182  case EUC_PointType:
183  if (myIndex == 0)
184  {
185  haspos = true;
186  pos = ((EUC_Point *)obj)->getPos();
187  }
188  break;
189  case EUC_LineType:
190  case EUC_CircleType:
191  if (myIndex >= 0 && myIndex <= 1)
192  {
193  haspos = true;
194  pos = ((EUC_Line *)obj)->getPt(myIndex);
195  }
196  break;
197  }
198 
199  if (haspos)
200  {
201  pt = new EUC_Point(pos);
202  applyLook(pt);
203  result.append(pt);
204  totalobj.append(pt);
205  }
206  }
207 }
208 
209 //
210 // EUC_ExprLineFromPoints
211 //
213 {
214  pta->addRef();
215  ptb->addRef();
216  myPtA = pta;
217  myPtB = ptb;
218 }
219 
221 {
222  myPtA->removeRef();
223  myPtB->removeRef();
224 }
225 
226 void
228  EUC_ObjectList &totalobj)
229 {
230  EUC_Line *line;
231  EUC_ObjectList ptalist, ptblist;
232  int i, n;
233  UT_Vector2 a, b;
234 
235  result.setSize(0);
236  myPtA->evaluateRecurse(ptalist, totalobj);
237  myPtB->evaluateRecurse(ptblist, totalobj);
238  n = SYSmin(ptalist.size(), ptblist.size());
239  for (i = 0; i < n; i++)
240  {
241  if (ptalist(i)->getType() == EUC_PointType &&
242  ptblist(i)->getType() == EUC_PointType)
243  {
244  a = ((EUC_Point *)ptalist(i))->getPos();
245  b = ((EUC_Point *)ptblist(i))->getPos();
246  line = new EUC_Line();
247  applyLook(line);
248  line->setPt(0, a);
249  line->setPt(1, b);
250  result.append(line);
251  totalobj.append(line);
252  }
253  }
254 }
255 
256 //
257 // EUC_ExprCircleFromPoints
258 //
260 {
261  center->addRef();
262  pt->addRef();
263  myCenter = center;
264  myPoint = pt;
265 }
266 
268 {
269  myCenter->removeRef();
270  myPoint->removeRef();
271 }
272 
273 void
275  EUC_ObjectList &totalobj)
276 {
277  EUC_Circle *circle;
278  EUC_ObjectList ptalist, ptblist;
279  int i, n;
280  UT_Vector2 a, b;
281 
282  result.setSize(0);
283  myCenter->evaluateRecurse(ptalist, totalobj);
284  myPoint->evaluateRecurse(ptblist, totalobj);
285  n = SYSmin(ptalist.size(), ptblist.size());
286  for (i = 0; i < n; i++)
287  {
288  if (ptalist(i)->getType() == EUC_PointType &&
289  ptblist(i)->getType() == EUC_PointType)
290  {
291  a = ((EUC_Point *)ptalist(i))->getPos();
292  b = ((EUC_Point *)ptblist(i))->getPos();
293  circle = new EUC_Circle();
294  applyLook(circle);
295  circle->setPt(0, a);
296  circle->setPt(1, b);
297  result.append(circle);
298  totalobj.append(circle);
299  }
300  }
301 }
302 
303 //
304 // EUC_ExprIntersect
305 //
307 {
308  expra->addRef();
309  exprb->addRef();
310  myExprA = expra;
311  myExprB = exprb;
312 }
313 
315 {
316  myExprA->removeRef();
317  myExprB->removeRef();
318 }
319 
320 void
322  EUC_ObjectList &totalobj)
323 {
324  EUC_Point *pt;
325  EUC_ObjectList ptalist, ptblist;
326  EUC_Object *obja, *objb;
327  int i, n;
328  UT_Vector2 pos;
329 
330  result.setSize(0);
331  myExprA->evaluateRecurse(ptalist, totalobj);
332  myExprB->evaluateRecurse(ptblist, totalobj);
333  n = SYSmin(ptalist.size(), ptblist.size());
334  for (i = 0; i < n; i++)
335  {
336  // Sort the types so lowest is obja.
337  if (ptalist(i)->getType() < ptblist(i)->getType())
338  {
339  obja = ptalist(i);
340  objb = ptblist(i);
341  }
342  else
343  {
344  objb = ptalist(i);
345  obja = ptblist(i);
346  }
347 
348  // This simplifies this double-switch...
349  if (obja->getType() == EUC_PointType)
350  {
351  // Points never intersect anything.
352  continue;
353  }
354 
355  if (obja->getType() == EUC_LineType)
356  {
357  // Either Line-Line or Line-Circle
358  if (objb->getType() == EUC_LineType)
359  {
360  // Line-Line intersection
361  UT_Vector3 p1, p2, v1, v2, isect;
362  int retcode;
363 
364  pos = ((EUC_Line *)obja)->getPt(0);
365  p1.assign(pos.x(), pos.y(), 0);
366  pos = ((EUC_Line *)obja)->getPt(1);
367  v1.assign(pos.x(), pos.y(), 0);
368  v1 -= p1;
369 
370  pos = ((EUC_Line *)objb)->getPt(0);
371  p2.assign(pos.x(), pos.y(), 0);
372  pos = ((EUC_Line *)objb)->getPt(1);
373  v2.assign(pos.x(), pos.y(), 0);
374  v2 -= p2;
375 
376  retcode = isect.lineIntersect(p1, v1, p2, v2);
377  // Non-parallel lines get a single intersection.
378  if (retcode != -1)
379  {
380  pos = isect;
381  pt = new EUC_Point(pos);
382  applyLook(pt);
383  result.append(pt);
384  totalobj.append(pt);
385  }
386  }
387  else
388  {
389  // Line-Circle isect.
390  UT_Vector2 p, v, center;
391  float radius, a, b, c, t0, t1;
392 
393  // x = p.x + v.x * t
394  // y = p.y + v.y * t
395  // Solve for:
396  // (x - c.x)^2 + (y - c.y) ^ 2 = r^2
397  // (v.x*t + (p.x - c.x))^2 + (v.y*t + (p.y - c.y))^2 = r^2
398  // Let c = p - c
399  // (v.x^2+v.y^2)*t^2
400  // + 2*(v.x*c.x+v.y*c.y)*t
401  // + (c.x^2+c.y^2-r^2) = 0
402  //
403 
404  p = ((EUC_Line *)obja)->getPt(0);
405  v = ((EUC_Line *)obja)->getPt(1);
406  v -= p;
407 
408  center = ((EUC_Circle *)objb)->getCenter();
409  radius = ((EUC_Circle *)objb)->getRadius();
410 
411  center = p - center;
412  a = dot(v, v);
413  b = 2 * dot(v, center);
414  c = dot(center, center) - radius*radius;
415  if (UT_RootFinder::quadratic(a, b, c, t0, t1))
416  {
417  // We consider it two intersections.
418  pos = p + t0 * v;
419  pt = new EUC_Point(pos);
420  applyLook(pt);
421  result.append(pt);
422  totalobj.append(pt);
423 
424  pos = p + t1 * v;
425  pt = new EUC_Point(pos);
426  applyLook(pt);
427  result.append(pt);
428  totalobj.append(pt);
429  }
430  }
431  }
432  else
433  {
434  // Must be Circle-Circle.
435  // Along the line between the centers, parameterized
436  // with arclength with t, height one one circle is
437  // hA(t)^2 = rA^2 - t^2
438  // Height on the other circle, where distance between them is d,
439  // hB(t)^2 = rB^2 - (t-d)^2
440  // We want hA == hB.
441  // We thus get
442  // rA^2 - t^2 = rB^2 - t^2 + 2td - d^2
443  // 2td = (rA^2 - rB^2 + d^2)
444  // t = (rA^2 - rB^2 + d^2) / 2d
445  // We can then sanity test t & directly compute the intersection.
446  float rA, rB, t, d, hA2, hB2;
447  UT_Vector2 cA, cB, v, perpv;
448 
449  rA = ((EUC_Circle *)obja)->getRadius();
450  cA = ((EUC_Circle *)obja)->getCenter();
451  rB = ((EUC_Circle *)objb)->getRadius();
452  cB = ((EUC_Circle *)objb)->getCenter();
453  v = cB;
454  v -= cA;
455  d = v.length();
456  v.normalize();
457  if (!SYSequalZero(d))
458  {
459  // Non-zero difference, a chance for intersection.
460  t = (rA*rA - rB*rB + d*d) / (2.0 * d);
461 
462  // Make sure neither of the squared heights are negative.
463  hA2 = rA*rA - t*t;
464  hB2 = rB*rB - (t-d)*(t-d);
465  if (hA2 >= 0 && hB2 >= 0)
466  {
467  // Get the perpindicular
468  perpv.x() = v.y();
469  perpv.y() = -v.x();
470 
471  hA2 = SYSsqrt(hA2);
472 
473  // Compute our new positions.
474  pos = cA + t * v + hA2 * perpv;
475  pt = new EUC_Point(pos);
476  applyLook(pt);
477  result.append(pt);
478  totalobj.append(pt);
479 
480  pos = cA + t * v - hA2 * perpv;
481  pt = new EUC_Point(pos);
482  applyLook(pt);
483  result.append(pt);
484  totalobj.append(pt);
485  }
486  }
487  }
488  }
489 }
490 
491 //
492 // EUC_ExprSelect
493 //
495 {
496  src->addRef();
497  mySource = src;
498  myIndex = idx;
499 }
500 
502 {
503  mySource->removeRef();
504 }
505 
506 void
508  EUC_ObjectList &totalobj)
509 {
510  EUC_ObjectList objlist;
511 
512  result.setSize(0);
513  mySource->evaluateRecurse(objlist, totalobj);
514 
515  if (myIndex >= 0 && myIndex < objlist.size())
516  result.append(objlist(myIndex));
517 }
518 
void applyLook(EUC_Object *obj)
void evaluateSubclass(EUC_ObjectList &result, EUC_ObjectList &totalobj) override
void setPt(int idx, const UT_Vector2 &pt)
Definition: EUC_Object.h:86
const GLdouble * v
Definition: glcorearb.h:837
void evaluateSubclass(EUC_ObjectList &result, EUC_ObjectList &totalobj) override
static EUC_Expression * getExprFromUid(int uid)
void evaluate(EUC_ObjectList &results)
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
EUC_ExprLineFromPoints(EUC_Expression *pta, EUC_Expression *ptb)
EUC_ExprIntersect(EUC_Expression *expra, EUC_Expression *exprb)
**But if you need a result
Definition: thread.h:613
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:818
EUC_ExprPointFromObject(EUC_Expression *src, int idx)
void evaluateSubclass(EUC_ObjectList &result, EUC_ObjectList &totalobj) override
exint size() const
Definition: UT_Array.h:646
void setSize(exint newsize)
Definition: UT_Array.h:666
virtual void evaluateSubclass(EUC_ObjectList &result, EUC_ObjectList &totalobj)=0
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector2.h:423
void setLook(bool visible, const UT_Vector3 &cd)
GLdouble n
Definition: glcorearb.h:2008
constexpr SYS_FORCE_INLINE T length() const noexcept
Definition: UT_Vector2.h:294
int lineIntersect(const UT_Vector3T< T > &p1, const UT_Vector3T< T > &v1, const UT_Vector3T< T > &p2, const UT_Vector3T< T > &v2)
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
Definition: CE_Vector.h:130
virtual EUC_ObjType getType() const =0
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
exint append()
Definition: UT_Array.h:142
GLdouble t
Definition: glad.h:2397
EUC_ExprCircleFromPoints(EUC_Expression *center, EUC_Expression *pt)
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:1069
void assign(T xx=0.0f, T yy=0.0f, T zz=0.0f)
Set the values of the vector components.
Definition: UT_Vector3.h:694
void setLook(bool visible, const UT_Vector3 &cd)
Definition: EUC_Object.C:48
void evaluateSubclass(EUC_ObjectList &result, EUC_ObjectList &totalobj) override
GLfloat GLfloat v1
Definition: glcorearb.h:817
EUC_ExprPoint(const UT_Vector2 &pos)
void evaluateRecurse(EUC_ObjectList &result, EUC_ObjectList &totalobj)
EUC_ExprSelect(EUC_Expression *src, int idx)
void evaluateSubclass(EUC_ObjectList &result, EUC_ObjectList &totalobj) override
static int quadratic(T a, T b, T c, T &v0, T &v1)
#define SYSmin(a, b)
Definition: SYS_Math.h:1539
SYS_FORCE_INLINE UT_StorageMathFloat_t< T > normalize() noexcept
Definition: UT_Vector2.h:309
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector2.h:425
void evaluateSubclass(EUC_ObjectList &result, EUC_ObjectList &totalobj) override
GLenum src
Definition: glcorearb.h:1793