#include "EUC_Expression.h"
#include <SYS/SYS_Math.h>
#include <UT/UT_Vector3.h>
#include <UT/UT_RootFinder.h>
using namespace HDK_Sample;
EUC_ExpressionList EUC_Expression::ourExpressionList;
int EUC_Expression::ourEvaluateTime = 0;
EUC_Expression::EUC_Expression()
{
myRefCount = 0;
myUid = ourExpressionList.entries();
myLastEvaluateTime = 0;
myCd = 1;
myVisible = true;
ourExpressionList.append(this);
}
EUC_Expression::~EUC_Expression()
{
ourExpressionList(getUid()) = 0;
}
void
EUC_Expression::addRef()
{
myRefCount++;
}
void
EUC_Expression::removeRef()
{
myRefCount--;
if (myRefCount <= 0)
delete this;
}
EUC_Expression *
EUC_Expression::getExprFromUid(int uid)
{
if (uid < 0 || uid >= ourExpressionList.entries())
return 0;
return ourExpressionList(uid);
}
void
EUC_Expression::setLook(bool visible, const UT_Vector3 &cd)
{
myVisible = visible;
myCd = cd;
}
void
EUC_Expression::applyLook(EUC_Object *obj)
{
obj->setLook(myVisible, myCd);
}
void
EUC_Expression::evaluate(EUC_ObjectList &results)
{
ourEvaluateTime++;
EUC_ObjectList tmp;
evaluateRecurse(tmp, results);
}
void
EUC_Expression::evaluateRecurse(EUC_ObjectList &result,
EUC_ObjectList &totalobj)
{
if (myLastEvaluateTime == ourEvaluateTime)
{
result = myObjectCache;
return;
}
myLastEvaluateTime = ourEvaluateTime;
myObjectCache.entries(0);
evaluateSubclass(myObjectCache, totalobj);
result = myObjectCache;
}
EUC_ExprPoint::EUC_ExprPoint(const UT_Vector2 &pos) : EUC_Expression()
{
myPos = pos;
}
void
EUC_ExprPoint::evaluateSubclass(EUC_ObjectList &result,
EUC_ObjectList &totalobj)
{
EUC_Point *pt;
pt = new EUC_Point(myPos);
applyLook(pt);
result.entries(0);
result.append(pt);
totalobj.append(pt);
}
EUC_ExprPointFromObject::EUC_ExprPointFromObject(EUC_Expression *src, int idx) : EUC_Expression()
{
src->addRef();
mySource = src;
myIndex = idx;
}
EUC_ExprPointFromObject::~EUC_ExprPointFromObject()
{
mySource->removeRef();
}
void
EUC_ExprPointFromObject::evaluateSubclass(EUC_ObjectList &result,
EUC_ObjectList &totalobj)
{
EUC_Point *pt;
EUC_ObjectList objlist;
EUC_Object *obj;
int i, n;
UT_Vector2 pos;
bool haspos;
result.entries(0);
mySource->evaluateRecurse(objlist, totalobj);
n = objlist.entries();
for (i = 0; i < n; i++)
{
obj = objlist(i);
haspos = false;
switch (obj->getType())
{
case EUC_PointType:
if (myIndex == 0)
{
haspos = true;
pos = ((EUC_Point *)obj)->getPos();
}
break;
case EUC_LineType:
case EUC_CircleType:
if (myIndex >= 0 && myIndex <= 1)
{
haspos = true;
pos = ((EUC_Line *)obj)->getPt(myIndex);
}
break;
}
if (haspos)
{
pt = new EUC_Point(pos);
applyLook(pt);
result.append(pt);
totalobj.append(pt);
}
}
}
EUC_ExprLineFromPoints::EUC_ExprLineFromPoints(EUC_Expression *pta, EUC_Expression *ptb) : EUC_Expression()
{
pta->addRef();
ptb->addRef();
myPtA = pta;
myPtB = ptb;
}
EUC_ExprLineFromPoints::~EUC_ExprLineFromPoints()
{
myPtA->removeRef();
myPtB->removeRef();
}
void
EUC_ExprLineFromPoints::evaluateSubclass(EUC_ObjectList &result,
EUC_ObjectList &totalobj)
{
EUC_Line *line;
EUC_ObjectList ptalist, ptblist;
int i, n;
UT_Vector2 a, b;
result.entries(0);
myPtA->evaluateRecurse(ptalist, totalobj);
myPtB->evaluateRecurse(ptblist, totalobj);
n = SYSmin(ptalist.entries(), ptblist.entries());
for (i = 0; i < n; i++)
{
if (ptalist(i)->getType() == EUC_PointType &&
ptblist(i)->getType() == EUC_PointType)
{
a = ((EUC_Point *)ptalist(i))->getPos();
b = ((EUC_Point *)ptblist(i))->getPos();
line = new EUC_Line();
applyLook(line);
line->setPt(0, a);
line->setPt(1, b);
result.append(line);
totalobj.append(line);
}
}
}
EUC_ExprCircleFromPoints::EUC_ExprCircleFromPoints(EUC_Expression *center, EUC_Expression *pt) : EUC_Expression()
{
center->addRef();
pt->addRef();
myCenter = center;
myPoint = pt;
}
EUC_ExprCircleFromPoints::~EUC_ExprCircleFromPoints()
{
myCenter->removeRef();
myPoint->removeRef();
}
void
EUC_ExprCircleFromPoints::evaluateSubclass(EUC_ObjectList &result,
EUC_ObjectList &totalobj)
{
EUC_Circle *circle;
EUC_ObjectList ptalist, ptblist;
int i, n;
UT_Vector2 a, b;
result.entries(0);
myCenter->evaluateRecurse(ptalist, totalobj);
myPoint->evaluateRecurse(ptblist, totalobj);
n = SYSmin(ptalist.entries(), ptblist.entries());
for (i = 0; i < n; i++)
{
if (ptalist(i)->getType() == EUC_PointType &&
ptblist(i)->getType() == EUC_PointType)
{
a = ((EUC_Point *)ptalist(i))->getPos();
b = ((EUC_Point *)ptblist(i))->getPos();
circle = new EUC_Circle();
applyLook(circle);
circle->setPt(0, a);
circle->setPt(1, b);
result.append(circle);
totalobj.append(circle);
}
}
}
EUC_ExprIntersect::EUC_ExprIntersect(EUC_Expression *expra, EUC_Expression *exprb) : EUC_Expression()
{
expra->addRef();
exprb->addRef();
myExprA = expra;
myExprB = exprb;
}
EUC_ExprIntersect::~EUC_ExprIntersect()
{
myExprA->removeRef();
myExprB->removeRef();
}
void
EUC_ExprIntersect::evaluateSubclass(EUC_ObjectList &result,
EUC_ObjectList &totalobj)
{
EUC_Point *pt;
EUC_ObjectList ptalist, ptblist;
EUC_Object *obja, *objb;
int i, n;
UT_Vector2 pos;
result.entries(0);
myExprA->evaluateRecurse(ptalist, totalobj);
myExprB->evaluateRecurse(ptblist, totalobj);
n = SYSmin(ptalist.entries(), ptblist.entries());
for (i = 0; i < n; i++)
{
if (ptalist(i)->getType() < ptblist(i)->getType())
{
obja = ptalist(i);
objb = ptblist(i);
}
else
{
objb = ptalist(i);
obja = ptblist(i);
}
if (obja->getType() == EUC_PointType)
{
continue;
}
if (obja->getType() == EUC_LineType)
{
if (objb->getType() == EUC_LineType)
{
UT_Vector3 p1, p2, v1, v2, isect;
int retcode;
pos = ((EUC_Line *)obja)->getPt(0);
p1.assign(pos.x(), pos.y(), 0);
pos = ((EUC_Line *)obja)->getPt(1);
v1.assign(pos.x(), pos.y(), 0);
v1 -= p1;
pos = ((EUC_Line *)objb)->getPt(0);
p2.assign(pos.x(), pos.y(), 0);
pos = ((EUC_Line *)objb)->getPt(1);
v2.assign(pos.x(), pos.y(), 0);
v2 -= p2;
retcode = isect.lineIntersect(p1, v1, p2, v2);
if (retcode != -1)
{
pos = isect;
pt = new EUC_Point(pos);
applyLook(pt);
result.append(pt);
totalobj.append(pt);
}
}
else
{
UT_Vector2 p, v, center, isect;
float radius, a, b, c, t0, t1;
p = ((EUC_Line *)obja)->getPt(0);
v = ((EUC_Line *)obja)->getPt(1);
v -= p;
center = ((EUC_Circle *)objb)->getCenter();
radius = ((EUC_Circle *)objb)->getRadius();
center = p - center;
a = dot(v, v);
b = 2 * dot(v, center);
c = dot(center, center) - radius*radius;
if (UT_RootFinder::quadratic(a, b, c, t0, t1))
{
pos = p + t0 * v;
pt = new EUC_Point(pos);
applyLook(pt);
result.append(pt);
totalobj.append(pt);
pos = p + t1 * v;
pt = new EUC_Point(pos);
applyLook(pt);
result.append(pt);
totalobj.append(pt);
}
}
}
else
{
float rA, rB, t, d, hA2, hB2;
UT_Vector2 cA, cB, v, perpv;
rA = ((EUC_Circle *)obja)->getRadius();
cA = ((EUC_Circle *)obja)->getCenter();
rB = ((EUC_Circle *)objb)->getRadius();
cB = ((EUC_Circle *)objb)->getCenter();
v = cB;
v -= cA;
d = v.length();
v.normalize();
if (!SYSequalZero(d))
{
t = (rA*rA - rB*rB + d*d) / (2.0 * d);
hA2 = rA*rA - t*t;
hB2 = rB*rB - (t-d)*(t-d);
if (hA2 >= 0 && hB2 >= 0)
{
perpv.x() = v.y();
perpv.y() = -v.x();
hA2 = SYSsqrt(hA2);
pos = cA + t * v + hA2 * perpv;
pt = new EUC_Point(pos);
applyLook(pt);
result.append(pt);
totalobj.append(pt);
pos = cA + t * v - hA2 * perpv;
pt = new EUC_Point(pos);
applyLook(pt);
result.append(pt);
totalobj.append(pt);
}
}
}
}
}
EUC_ExprSelect::EUC_ExprSelect(EUC_Expression *src, int idx) : EUC_Expression()
{
src->addRef();
mySource = src;
myIndex = idx;
}
EUC_ExprSelect::~EUC_ExprSelect()
{
mySource->removeRef();
}
void
EUC_ExprSelect::evaluateSubclass(EUC_ObjectList &result,
EUC_ObjectList &totalobj)
{
EUC_ObjectList objlist;
result.entries(0);
mySource->evaluateRecurse(objlist, totalobj);
if (myIndex >= 0 && myIndex < objlist.entries())
result.append(objlist(myIndex));
}