/*****
* runpath3.in
*
* Runtime functions for path3 operations.
*
*****/
pair => primPair()
triple => primTriple()
path3 => primPath3()
boolarray* => booleanArray()
realarray* => realArray()
realarray2* => realArray2()
triplearray* => tripleArray()
triplearray2* => tripleArray2()
#include "path3.h"
#include "array.h"
#include "drawsurface.h"
using namespace camp;
using namespace vm;
typedef array boolarray;
typedef array realarray;
typedef array realarray2;
typedef array triplearray;
typedef array triplearray2;
using types::booleanArray;
using types::realArray;
using types::realArray2;
using types::tripleArray;
using types::tripleArray2;
// Autogenerated routines:
path3 path3(triplearray *pre, triplearray *point, triplearray *post,
boolarray *straight, bool cyclic)
{
size_t n=checkArrays(pre,point);
checkEqual(n,checkArray(post));
checkEqual(n,checkArray(straight));
mem::vector<solvedKnot3> nodes(n);
for(size_t i=0; i < n; ++i) {
nodes[i].pre=read<triple>(pre,i);
nodes[i].point=read<triple>(point,i);
nodes[i].post=read<triple>(post,i);
nodes[i].straight=read<bool>(straight,i);
}
return path3(nodes,(Int) n,cyclic);
}
path3 :nullPath3()
{
return nullpath3;
}
bool ==(path3 a, path3 b)
{
return a == b;
}
bool !=(path3 a, path3 b)
{
return !(a == b);
}
triple point(path3 p, Int t)
{
return p.point((Int) t);
}
triple point(path3 p, real t)
{
return p.point(t);
}
triple precontrol(path3 p, Int t)
{
return p.precontrol((Int) t);
}
triple precontrol(path3 p, real t)
{
return p.precontrol(t);
}
triple postcontrol(path3 p, Int t)
{
return p.postcontrol((Int) t);
}
triple postcontrol(path3 p, real t)
{
return p.postcontrol(t);
}
triple dir(path3 p, Int t, Int sign=0, bool normalize=true)
{
return p.dir(t,sign,normalize);
}
triple dir(path3 p, real t, bool normalize=true)
{
return p.dir(t,normalize);
}
triple accel(path3 p, Int t, Int sign=0)
{
return p.accel(t,sign);
}
triple accel(path3 p, real t)
{
return p.accel(t);
}
real radius(path3 p, real t)
{
triple v=p.dir(t,false);
triple a=p.accel(t);
real d=dot(a,v);
real v2=v.abs2();
real a2=a.abs2();
real denom=v2*a2-d*d;
real r=v2*sqrt(v2);
return denom > 0 ? r/sqrt(denom) : 0.0;
}
real radius(triple z0, triple c0, triple c1, triple z1, real t)
{
triple v=(3.0*(z1-z0)+9.0*(c0-c1))*t*t+(6.0*(z0+c1)-12.0*c0)*t+3.0*(c0-z0);
triple a=6.0*(z1-z0+3.0*(c0-c1))*t+6.0*(z0+c1)-12.0*c0;
real d=dot(a,v);
real v2=v.abs2();
real a2=a.abs2();
real denom=v2*a2-d*d;
real r=v2*sqrt(v2);
return denom > 0 ? r/sqrt(denom) : 0.0;
}
path3 reverse(path3 p)
{
return p.reverse();
}
path3 subpath(path3 p, Int a, Int b)
{
return p.subpath((Int) a, (Int) b);
}
path3 subpath(path3 p, real a, real b)
{
return p.subpath(a,b);
}
Int length(path3 p)
{
return p.length();
}
bool cyclic(path3 p)
{
return p.cyclic();
}
bool straight(path3 p, Int t)
{
return p.straight(t);
}
path3 unstraighten(path3 p)
{
return p.unstraighten();
}
// Return the maximum perpendicular deviation of segment i of path3 g
// from a straight line.
real straightness(path3 p, Int t)
{
if(p.straight(t)) return 0;
triple z0=p.point(t);
triple u=unit(p.point(t+1)-z0);
return ::max(length(perp(p.postcontrol(t)-z0,u)),
length(perp(p.precontrol(t+1)-z0,u)));
}
// Return the maximum perpendicular deviation of z0..controls c0 and c1..z1
// from a straight line.
real straightness(triple z0, triple c0, triple c1, triple z1)
{
triple u=unit(z1-z0);
return ::max(length(perp(c0-z0,u)),length(perp(c1-z0,u)));
}
bool piecewisestraight(path3 p)
{
return p.piecewisestraight();
}
real arclength(path3 p)
{
return p.arclength();
}
real arctime(path3 p, real dval)
{
return p.arctime(dval);
}
realarray* intersect(path3 p, path3 q, real fuzz=-1)
{
bool exact=fuzz <= 0.0;
if(fuzz < 0)
fuzz=BigFuzz*::max(::max(length(p.max()),length(p.min())),
::max(length(q.max()),length(q.min())));
std::vector<real> S,T;
real s,t;
if(intersections(s,t,S,T,p,q,fuzz,true,exact)) {
array *V=new array(2);
(*V)[0]=s;
(*V)[1]=t;
return V;
} else
return new array(0);
}
realarray2* intersections(path3 p, path3 q, real fuzz=-1)
{
bool exact=fuzz <= 0.0;
if(fuzz < 0)
fuzz=BigFuzz*::max(::max(length(p.max()),length(p.min())),
::max(length(q.max()),length(q.min())));
bool single=!exact;
real s,t;
std::vector<real> S,T;
bool found=intersections(s,t,S,T,p,q,fuzz,single,exact);
if(!found) return new array(0);
array *V;
if(single) {
V=new array(1);
array *Vi=new array(2);
(*V)[0]=Vi;
(*Vi)[0]=s;
(*Vi)[1]=t;
} else {
size_t n=S.size();
V=new array(n);
for(size_t i=0; i < n; ++i) {
array *Vi=new array(2);
(*V)[i]=Vi;
(*Vi)[0]=S[i];
(*Vi)[1]=T[i];
}
}
stable_sort(V->begin(),V->end(),run::compare2<real>());
return V;
}
realarray2* intersections(path3 p, triplearray2 *P, real fuzz=-1)
{
triple *A;
copyArray2C(A,P,true,4);
if(fuzz <= 0) fuzz=BigFuzz*::max(::max(length(p.max()),length(p.min())),
norm(A,16));
std::vector<real> T,U,V;
intersections(T,U,V,p,A,fuzz);
delete[] A;
size_t n=T.size();
array *W=new array(n);
for(size_t i=0; i < n; ++i) {
array *Wi=new array(3);
(*W)[i]=Wi;
(*Wi)[0]=T[i];
(*Wi)[1]=U[i];
(*Wi)[2]=V[i];
}
return W; // Sorting will done in asy.
}
Int size(path3 p)
{
return p.size();
}
path3 &(path3 p, path3 q)
{
return camp::concat(p,q);
}
triple min(path3 p)
{
return p.min();
}
triple max(path3 p)
{
return p.max();
}
realarray *mintimes(path3 p)
{
array *V=new array(3);
triple v=p.mintimes();
(*V)[0]=v.getx();
(*V)[1]=v.gety();
(*V)[2]=v.getz();
return V;
}
realarray *maxtimes(path3 p)
{
array *V=new array(3);
triple v=p.maxtimes();
(*V)[0]=v.getx();
(*V)[1]=v.gety();
(*V)[2]=v.getz();
return V;
}
path3 Operator *(realarray2 *t, path3 g)
{
return transformed(*t,g);
}
pair minratio(path3 g)
{
return g.ratio(::min);
}
pair maxratio(path3 g)
{
return g.ratio(::max);
}