Esempio n. 1
0
bool Cylinder3D::intersects(const Line3D& line,Real* tmin,Real* tmax) const
{
  Real axistmin,axistmax;

  //quick reject - infinite cylinder
  Vector3 src=line.source-center;
  const Vector3& dir=line.direction;
  assert(FuzzyEquals(axis.normSquared(),One));
  //quadratic equation
  Real a,b,c;
  Real dv,sv;
  dv = dir.dot(axis);
  sv = src.dot(axis);
  a=dir.normSquared()-Sqr(dv);
  b=Two*(dir.dot(src)-sv*dv);
  c=src.normSquared()-Sqr(sv)-Sqr(radius);
  int nroots=quadratic(a,b,c,axistmin,axistmax);
  //TODO: if the line is contained within the cylinder, ignore this
  if(nroots == 0) return false;
  else if(nroots == 1) axistmax=axistmin;
  else if(nroots == 2) {
    if(axistmin > axistmax) std::swap(axistmin,axistmax);
  }
  else if(nroots == -1) return false;
  else return false;  //what case is this?

  //projection of intersection pts on the cyl axis
  Real axisumin,axisumax;
  Vector3 temp;
  line.eval(axistmin,temp);  axisumin = axis.dot(temp-center);
  line.eval(axistmax,temp);  axisumax = axis.dot(temp-center);

  //now check the caps
  Real tc;
  Circle3D cir;
  if(axisumin < 0) {   //hits a cap first
    if(dv > 0) //line points along axis
      getBase(cir);
    else  //line points against axis
      getCap(cir);
    if(!cir.intersects(line,&tc)) return false;
    axistmin = tc;
  }
  if(axisumin > height) {  //hits a cap last
    if(dv > 0) //line points along axis
      getCap(cir);
    else  //line points against axis
      getBase(cir);
    if(!cir.intersects(line,&tc)) return false;
    axistmax = tc;
  }
  //if(axistmin > axistmax) return false;
  if(tmin) *tmin=axistmin;
  if(tmax) *tmax=axistmax;
  return true;
}
Esempio n. 2
0
bool Circle3D::intersects(const Line3D& l,Real* _t) const
{
  Plane3D p;
  getPlane(p);
  Real t;
  if(p.intersectsLine(l,&t)) {
    if(t == Inf)  { //line lies in plane
      t = l.closestPointParameter(center);
    }
    if(_t) (*_t)=t;
    Point3D pt;
    l.eval(t,pt);
    return DistanceLEQ(pt,center,radius);
  }
  return false;
}
Esempio n. 3
0
bool TransformWidget::Hover(int x,int y,Camera::Viewport& viewport,double& distance)
{
  Real globalScale = 1.0;
  if(scaleToScreen) {
    float sx,sy,sz;
    viewport.project(T.t,sx,sy,sz);
    globalScale = sz/viewport.scale;
  }
  distance = Inf;
  int oldHoverItem = hoverItem;
  hoverItem = -1;
  Ray3D r;
  viewport.getClickSource(x,y,r.source);
  viewport.getClickVector(x,y,r.direction);
  //check origin
  if(enableTranslation && enableOriginTranslation) {
    Sphere3D s;
    s.center = T.t;
    s.radius = originRadius*globalScale;
    Real tmin,tmax;
    if(s.intersects(r,&tmin,&tmax)) {
      distance = tmin;
      hoverItem = 0;
    }
  }
  //check translation axes
  for(int i=0;i<3;i++) {
    if(!enableTranslation) break;
    if(!enableTranslationAxes[i]) continue;
    Line3D axisLine;
    axisLine.source = T.t;
    axisLine.direction = Vector3(T.R.col(i));
    Real t,u;
    axisLine.closestPoint(r,t,u);
    t = Clamp(t,0.0,axisLength*globalScale);
    u = Clamp(u,0.0,Inf);
    Vector3 paxis,pray;
    axisLine.eval(t,paxis);
    r.eval(u,pray);
    if(paxis.distanceSquared(pray) <= Sqr(axisRadius*globalScale)) {
      if(u < distance) {
	distance = u;
	hoverItem = 1+i;
      }
    }
  }
  if(enableRotation) {
    //check rotation rings
    Circle3D c;
    c.center = T.t;
    for(int i=0;i<3;i++) {
      if(!enableRotationAxes[i]) continue;
      c.axis = Vector3(T.R.col(i));
      c.radius = ringOuterRadius*globalScale;
      Real t;
      if(c.intersects(r,&t) && t >= 0) {
	c.radius = ringInnerRadius*globalScale;
	if(!c.intersects(r,NULL)) {
	  if(t < distance) {
	    distance = t;
	    hoverItem = i+4;
	  }
	}
      }
    }
  }
  if(enableRotation && enableOuterRingRotation) {
    //check outer ring
    Circle3D c;
    c.center = T.t;
    viewport.getViewVector(c.axis);
    c.radius = (ringOuterRadius+arrowHeight)*globalScale;
    Real t;
    if(c.intersects(r,&t) && t >= 0) {
      c.radius = (ringInnerRadius+arrowHeight)*globalScale;
      if(!c.intersects(r,NULL)) {
	if(t < distance) {
	  distance = t;
	  hoverItem = 7;
	}
      }
    }
    clickAxis = c.axis;
  }
  if(hoverItem != oldHoverItem) Refresh();
  r.eval(distance,hoverPos);
  return hoverItem != -1;
}