Esempio n. 1
0
static inline bool findInflections(qreal a, qreal b, qreal c,
                                   qreal *t1 , qreal *t2, qreal *tCups)
{
    qreal r1 = 0, r2 = 0;

    short rootsCount = quadraticRoots(a, b, c, &r1, &r2);

    if (rootsCount >= 1) {
        if (r1 < r2) {
            *t1 = r1;
            *t2 = r2;
        } else {
            *t1 = r2;
            *t2 = r1;
        }
        if (!qFuzzyIsNull(a))
            *tCups = qreal(0.5) * (-b / a);
        else
            *tCups = 2;

        return true;
    }

    return false;
}
Esempio n. 2
0
RayResult* NonhierSphere::findIntersections(const Ray& ray) {

  // Will use quadratic solver.
  double A = ray.dir.length2();

  double B = 2 * ray.dir.dot(ray.pos - m_pos);

  double C = (ray.pos - m_pos).length2() - m_radius*m_radius;

  double roots[2];
  size_t num_roots = quadraticRoots(A, B, C, roots);

  std::vector<Intersection> intersections;

  const double EPSILON = 0.01;
  if (num_roots > 0) {
    double t = roots[0];
    if (num_roots == 2 && roots[1] > EPSILON && roots[1] < t) {
      t = roots[1];
    }
    if (t > EPSILON) {
      const Point3D p = ray.pos + t*ray.dir;
      Vector3D normal = p - m_pos;
      normal.normalize();
      //std::cout << "INTERSECTION for ray " << ray << " with params " << t << ", " << p << std::endl;
      intersections.push_back(Intersection(
        p, normal, NULL
      ));
    }
  }

  return new RayResult(intersections, 1);
}
Esempio n. 3
0
int verticalIntersect(double axisIntercept) {
    double D = quad[2].x; // f
    double E = quad[1].x; // e
    double F = quad[0].x; // d
    D += F - 2 * E; // D = d - 2*e + f
    E -= F; // E = -(d - e)
    F -= axisIntercept;
    return quadraticRoots(D, E, F, intersections.fT[0]);
}
Esempio n. 4
0
// from SkGeometry.cpp (and Numeric Solutions, 5.6)
int cubicRoots(double A, double B, double C, double D, double t[3]) {
    if (approximately_zero(A)) {  // we're just a quadratic
        return quadraticRoots(B, C, D, t);
    }
    double a, b, c;
    {
        double invA = 1 / A;
        a = B * invA;
        b = C * invA;
        c = D * invA;
    }
    double a2 = a * a;
    double Q = (a2 - b * 3) / 9;
    double R = (2 * a2 * a - 9 * a * b + 27 * c) / 54;
    double Q3 = Q * Q * Q;
    double R2MinusQ3 = R * R - Q3;
    double adiv3 = a / 3;
    double* roots = t;
    double r;

    if (R2MinusQ3 < 0)   // we have 3 real roots
    {
        double theta = acos(R / sqrt(Q3));
        double neg2RootQ = -2 * sqrt(Q);

        r = neg2RootQ * cos(theta / 3) - adiv3;
        if (is_unit_interval(r))
            *roots++ = r;

        r = neg2RootQ * cos((theta + 2 * PI) / 3) - adiv3;
        if (is_unit_interval(r))
            *roots++ = r;

        r = neg2RootQ * cos((theta - 2 * PI) / 3) - adiv3;
        if (is_unit_interval(r))
            *roots++ = r;
    }
    else                // we have 1 real root
    {
        double A = fabs(R) + sqrt(R2MinusQ3);
        A = cube_root(A);
        if (R > 0) {
            A = -A;
        }
        if (A != 0) {
            A += Q / A;
        }
        r = A - adiv3;
        if (is_unit_interval(r))
            *roots++ = r;
    }
    return (int)(roots - t);
}
Esempio n. 5
0
int intersect() {
/*
    solve by rotating line+quad so line is horizontal, then finding the roots
    set up matrix to rotate quad to x-axis
    |cos(a) -sin(a)|
    |sin(a)  cos(a)|
    note that cos(a) = A(djacent) / Hypoteneuse
              sin(a) = O(pposite) / Hypoteneuse
    since we are computing Ts, we can ignore hypoteneuse, the scale factor:
    |  A     -O    |
    |  O      A    |
    A = line[1].x - line[0].x (adjacent side of the right triangle)
    O = line[1].y - line[0].y (opposite side of the right triangle)
    for each of the three points (e.g. n = 0 to 2)
    quad[n].y' = (quad[n].y - line[0].y) * A - (quad[n].x - line[0].x) * O
*/
    double adj = line[1].x - line[0].x;
    double opp = line[1].y - line[0].y;
    double r[3];
    for (int n = 0; n < 3; ++n) {
        r[n] = (quad[n].y - line[0].y) * adj - (quad[n].x - line[0].x) * opp;
    }
    double A = r[2];
    double B = r[1];
    double C = r[0];
    A += C - 2 * B; // A = a - 2*b + c
    B -= C; // B = -(b - c)
    int roots = quadraticRoots(A, B, C, intersections.fT[0]);
    for (int index = 0; index < roots; ) {
        double lineT = findLineT(intersections.fT[0][index]);
        if (lineIntersects(lineT, index, roots)) {
            ++index;
        }
    }
    return roots;
}
Esempio n. 6
0
/* Coefficients :  x^4 + C[0] x^3  + C[1] x^2 + C[2] x  + C[3] */
size_t quarticRoots( 
	double a, double b, double c, double d, double roots[4] )
{
	double h,h1,h2,H,   g,g1,g2,G, n, m, en, em, y;
	double cubic[3];	/* Cubic and quadratic coefficients */
	int i, nr;

	/* Find the a real root of a certain cubic */
	cubic[0] = -2.0*b;
	cubic[1] = b*b + a*c - 4*d;
	cubic[2] = c*c - a*b*c + a*a*d;
	nr = cubicRoots( cubic[0], cubic[1], cubic[2], roots );

	if( nr == 1 ) {
		y = PolishRoot( 3, cubic[0], cubic[1], cubic[2], 0.0, roots[0] );
	} else {
		if( b < 0 && d < 0 ) {
			y = PolishRoot( 3, cubic[0], cubic[1], cubic[2], 0.0, roots[2] );
		} else {
			y = PolishRoot( 3, cubic[0], cubic[1], cubic[2], 0.0, roots[0] );
		}
	}

	g1 = a/2.0;
	h1 = (b-y)/2.0;
	if( y < 0 ) {
		n = a*a - 4*y;
		if( n <= 0 ) {
			return 0;
		}
		g2 = sqrt(n);
		if( g2 == 0 ) {
			return 0;
		}
		h2 = (a*((b-y)/2.0) - c) / g2;
		g2 /= 2.0;
	} else if( y > 0 && d > 0 && b < 0 ) {
		m = (b-y)*(b-y) - 4*d;
		if( m <= 0 ) {
			return 0;
		}
		h2 = sqrt(m);
		if( h2 == 0 ) {
			return 0;
		}
		g2 = (a*h1 - c) / h2;
		h2 /= 2.0;
	} else {
		n = a*a - 4*y;
		m = (b-y)*(b-y) - 4*d;
		en = b*b + 2.*fabs(b*y) + y*y + 4*fabs(d);
		em = a*a + 4.*fabs(y);
		if( m*en > n*em ) {		/* use m */
			if( m <= 0 ) { 
				return 0; 
			}
			h2 = sqrt(m);
			if( h2 == 0 ) { 
				return 0; 
			}
			g2 = (a*h1 - c) / h2;
			h2 /= 2.0;
		} else {			/* use n */
			if (n <= 0) {
				return 0;
			}
			g2 = sqrt(n);
			if (g2 == 0) { 
				return 0; 
			}
			h2 = (a*( (b-y)/2.0) - c) / g2;
			g2 /= 2.0;
		}
	}

	if( SIGN(g1) == SIGN(g2) ) {
		G = g1 + g2;
		g = (G==0) ? g1-g2  : y/G;
	} else {
		g = g1 - g2;
		G = (g == 0) ?  g1+g2 : y/g;
	}
	if( SIGN(h1) == SIGN(h2) ) {
		H = h1+h2;
		h = (H == 0) ? h1-h2  : d/H;
	} else {
		h = h1 - h2;
		H = (h == 0) ? h1+h2  : d/h;
	}

	nr = quadraticRoots( 1.0, G, H, roots );
	nr += quadraticRoots( 1.0, g, h, roots+nr );

	for( i=0; i < nr; ++i ) {
		roots[i] = PolishRoot( 4, a, b, c, d, roots[i] );
	}

	/* remove non-roots */
	//      fprintf(stderr,"REMOVE NONROOTS %d\n",nr);
	for ( i=0; i < nr; i++ ) {
		double r;
		r = (((roots[i]+a)*roots[i]+b)*roots[i]+c)*roots[i]+d;
		//              fprintf(stderr,"root %d is %g\n",i,r);
		if ( fabs(r)>1e-4 ) {
			roots[i] = roots[nr-1];
			nr--; i--;
		}
	}

	return nr;
}
Esempio n. 7
0
HitInfo Cone::intersects(Point3D origin, Vector3D dir) const {
  HitInfo info;
  double A = dir[0] * dir[0] + dir[2] * dir[2] - dir[1] * dir[1];
  double B = 2 * (origin[0] * dir[0] + origin[2] * dir[2] - (origin[1] - 1) * dir[1]);
  double C = origin[0] * origin[0]  + origin[2] * origin[2] - (origin[1] - 1.0) * 
	(origin[1] - 1.0);
  double roots[2]; 
  int num_roots = quadraticRoots(A, B, C, roots);

  if (dir[1] != 0.0) {
	Hit hit;
	double t3 = (0.0 - origin[1]) / dir[1];
	Point3D p = origin + t3 * dir;
	if (t3 > 0.0 && (p - Point3D(0.0, 0.0, 0.0)).length() <= 1.0) {
	  hit.normal = Vector3D(0.0, -1.0, 0.0);
	  hit.intersection = p;
	  hit.t = t3;
	  info.hits.push_back(hit);
	}
  }

  if (num_roots == 1 && roots[0] > 0.0) {
	// one hit on the cone
	Point3D p = origin + roots[0] * dir;
	if (p[1] >= 0.0 && p[1] <= 1.0) {
	  Hit hit;
	  hit.normal = Vector3D(p[0], 0.5, p[2]);
	  hit.intersection = p;
	  hit.t = roots[0];
	  info.hits = Hit::insert_hit_in_order(info.hits, hit);
	}
  } else if (num_roots == 2) {
	// two hits on cone
	Point3D p0 = origin + roots[0] * dir;
	if (roots[0] > 0.0 && p0[1] >= 0.0 && p0[1] <= 1.0) {
	  Hit h;
	  h.t = roots[0];
	  h.intersection = p0;
	  h.normal = Vector3D(p0[0], 0.0, p0[2]);
	  info.hits = Hit::insert_hit_in_order(info.hits, h);
	}

	Point3D p1 = origin + roots[1] * dir;
	if (roots[1] > 0.0 && p1[1] >= 0.0 && p1[1] <= 1.0) {
	  Hit h;
	  h.t = roots[1];
	  h.intersection = p1;
	  h.normal = Vector3D(p1[0], 0.0, p1[2]);
	  info.hits = Hit::insert_hit_in_order(info.hits, h);
	}
  }

  std::vector<Hit> final_hits;
  for (unsigned int i = 0; i < info.hits.size(); i++) {
	double len = (info.hits.at(i).intersection - origin).length();
	if (len > EPSILON) {
	  Vector3D Vn = Vector3D(0.0, 1.0, 0.0);
	  Vector3D Ve = Vector3D(1.0, 0.0, 0.0);
	  Vector3D Vp = info.hits.at(i).intersection - Point3D(0.0, 0.5, 0.0);
	  Vp.normalize();
	  double phi = acos(-Vn.dot(Vp)); 
	  double theta = (acos(Vp.dot(Ve)) / sin(phi)) / (2 * M_PI);
	  double u = (Vp.dot(Vn.cross(Ve)) > 0) ? theta : 1 - theta;
	  double v = phi / M_PI;
	  if (u < 0) {
		u = 0.0;
	  }
	  if (u > 1.0) {
		u = 1.0;
	  }
	  if (v < 0.0) {
		v = 0.0;
	  }
	  if (v > 1.0) {
		v = 1.0;
	  }
	  info.hits.at(i).tex_coords[0] = u;
	  info.hits.at(i).tex_coords[1] = v;
	  info.hits.at(i).in_shadow = (len > EPSILON) && (dir.length() > len);
	  final_hits.push_back(info.hits.at(i));
	}
  }
  info.hits = final_hits;

  if (info.hits.size() == 2) {
	info.lines.push_back(std::make_pair(info.hits.at(0), info.hits.at(1)));
	info.hits.clear();
  }
  return info;
}
Esempio n. 8
0
HitInfo Primitive::hits_sphere(Point3D origin, Vector3D dir, Point3D pos, double radius) {
  HitInfo info;
  Vector3D center_to_origin = origin - pos;
  double A = dir.dot(dir);
  double B = 2 * dir.dot(center_to_origin);
  double C = center_to_origin.dot(center_to_origin) - (radius * radius);
  double roots[2]; 
  int num_roots = quadraticRoots(A, B, C, roots);

  // if D has no roots, then it doesn't intersect.
  if (num_roots < 1) {
	return info;
  } else if (num_roots == 1 && roots[0] > 0) {
	Hit h;
	h.intersection = origin + roots[0] * dir;
	info.hits.push_back(h);
  } else {
	double t1 = roots[0];
	double t2 = roots[1];

	if (t1 <= 0.0 && t2 <= 0.0) {
	  return info;
	} 
	if (t1 >= 0.0) {
	  Hit h;
	  h.intersection = origin + t1 * dir;
	  h.t = t1;
	  info.hits = Hit::insert_hit_in_order(info.hits, h);
	}	
	if (t2 >= 0.0) {
	  Hit h;
	  h.intersection = origin + t2 * dir;
	  h.t = t2;
	  info.hits = Hit::insert_hit_in_order(info.hits, h);
	}
  }

  std::vector<Hit> final_hits;
  for (unsigned int i = 0; i < info.hits.size(); i++) {
	double len = (info.hits.at(i).intersection - origin).length();
	if (len > EPSILON) {
	  info.hits.at(i).in_shadow = (len > EPSILON) && (dir.length() > len);
	  info.hits.at(i).normal = info.hits.at(i).intersection - pos;
	  Vector3D Vn = Vector3D(0.0, 1.0, 0.0);
	  Vector3D Ve = Vector3D(1.0, 0.0, 0.0);
	  Vector3D Vp = info.hits.at(i).intersection - pos;
	  Vp.normalize();

	  //////////////////
	 //// double phi = acos(-Vn.dot(Vp)); 


	 // double theta = (acos(Vp.dot(Ve)) / sin(phi)) / (2 * M_PI);
	 // double u = (Vp.dot(Vn.cross(Ve)) > 0) ? theta : 1 - theta;


	  /////correct?

    double theta = atan2(-Vp[2], Vp[0]);
    double phi = acos(-Vp[1] / radius);

	  ///////////
    double u = (theta + M_PI) / (2 * M_PI);
	  double v = phi / M_PI;
	  /*
	  if (u < 0) {
		u = 0.0;
	  }
	  if (u > 1.0) {
		u = 1.0;
	  }
	  if (v < 0.0) {
		v = 0.0;
	  }
	  if (v > 1.0) {
		v = 1.0;
	  }
	  */
	  //std::cout <<"uv: " <<  u << " " << v << std::endl;
	  info.hits.at(i).tex_coords[0] = u;
	  info.hits.at(i).tex_coords[1] = v;
	  info.hits.at(i).pu = Vector3D(-radius*sin(theta)*sin(phi), 0, -radius*cos(theta)*sin(phi));
      info.hits.at(i).pv = Vector3D(radius*cos(theta)*cos(phi), radius*sin(phi), -radius*sin(theta)*cos(phi));
	  final_hits.push_back(info.hits.at(i));
	}
  }
  info.hits = final_hits;
  if (info.hits.size() == 2) {
	info.lines.push_back(std::make_pair(info.hits.at(0), info.hits.at(1)));
	info.hits.clear();
  }
  return info;
}