TEST(OctreeTest, RayBoxTest) { BoundingBox box(glm::vec3(0.0f), glm::vec3(1.0f)); float t_near, t_far; Ray ray0(glm::vec3(0.5f), glm::vec3(0.5f)); EXPECT_TRUE(box.Intersect(ray0, t_near, t_far)); Ray ray1(glm::vec3(0.5f, 0.5f, 0.25f), glm::vec3(0.5f)); EXPECT_TRUE(box.Intersect(ray1, t_near, t_far)); }
TEST(CubeTest, HasIntersection) { Cube cube; Ray ray1(Point3(0, 0, 2), Vector3(0, 0, -1)); EXPECT_TRUE(cube.HasIntersection(ray1, 2)); EXPECT_FALSE(cube.HasIntersection(ray1, 0.5)); Ray ray2(Point3(0, 0, 2), Vector3(0, 0, 1)); EXPECT_FALSE(cube.HasIntersection(ray2, 20)); }
void Ray2Tests::testBasics() { Ray2 ray1(Point2(2.0f, 0.0f), Vector2(2.0f, 0.0f)); Ray2 ray2(Point2(1.0f, 1.0f), Vector2(2.0f, 2.0f)); CPTAssert(ray1.origin() == Point2(2.0f, 0.0f)); CPTAssert(ray1.direction() == Point2(1.0f, 0.0f)); CPTAssert(ray2.origin() == Point2(1.0f, 1.0f)); CPTAssert(ray2.direction() == Point2(1.0f, 1.0f).unit()); }
TEST(RayTest, equality) { Geom::Point3D origin(0, 0, 0); Geom::Vector3D direction(1, 1, 1); Geom::Ray ray1(origin, direction); Geom::Ray ray2(origin, direction); EXPECT_EQ(ray1, ray2); Geom::Ray ray3(origin, Geom::Vector3D(2, 3, 2)); EXPECT_NE(ray1, ray3); }
void tst_QRay3D::compare() { Qt3DRender::RayCasting::QRay3D ray1(QVector3D(10, 20, 30), QVector3D(-3, -4, -5)); Qt3DRender::RayCasting::QRay3D ray2(QVector3D(10, 20, 30), QVector3D(1.5f, 2.0f, 2.5f)); Qt3DRender::RayCasting::QRay3D ray3(QVector3D(0, 20, 30), QVector3D(-3, -4, -5)); QVERIFY(ray1 == ray1); QVERIFY(!(ray1 != ray1)); QVERIFY(qFuzzyCompare(ray1, ray1)); QVERIFY(ray1 != ray2); QVERIFY(!(ray1 == ray2)); QVERIFY(!qFuzzyCompare(ray1, ray2)); QVERIFY(ray1 != ray3); QVERIFY(!(ray1 == ray3)); QVERIFY(!qFuzzyCompare(ray1, ray3)); }
// === Ray tests === TEST(RayTests, ReflectionTest) { // ^ // Reflection: |/ // --->/ Ray ray1(ZERO_VEC, X_NORM_VEC); Ray normRay1(glm::dvec3(5.0, 0.0, 0.0), glm::dvec3(-1.0, 1.0, 0.0)); Ray reflected1 = ray1.Reflect(normRay1); ASSERT_VEC_NEAR(reflected1.GetOrigin(), normRay1.GetOrigin(), EPS_STRONG); ASSERT_VEC_NEAR(reflected1.GetDirection(), Y_NORM_VEC, EPS_WEAK); // Reflection exactly backwards. ---> | // <---| Ray normRay2(glm::dvec3(10.0, 0.0, 0.0), -X_NORM_VEC); Ray reflected2 = ray1.Reflect(normRay2); ASSERT_VEC_NEAR(reflected2.GetOrigin(), normRay2.GetOrigin(), EPS_STRONG); ASSERT_VEC_NEAR(reflected2.GetDirection(), -1.0 * ray1.GetDirection(), EPS_STRONG); }
//! Check if point lays inside polygon (polygon must be in one plane) bool Polygon3::IsPointInside(const Vector3 & pt) { // Do not check if this is not a polygon if (pointCount <= 2)return false; UpdatePlaneFromPoints(); float planeDist = plane.DistanceToPoint(pt); // if not on plane exit if (!FLOAT_EQUAL(planeDist, 0.0f))return false; int intersectionsCount = 0; Vector2 ray0(pt.x, pt.y); Vector2 ray1(((points[0].x + points[1].x) / 2.0f) + 1000000.0f, ((points[0].y + points[1].y) / 2.0f) + 100000.0f); /* If you enabling debug intersections do not forget to call this function inside Draw of your application. If you'll call it inside update or mouse or keyboard input functions you can not get any output. */ //#define DEBUG_DRAW_INTERSECTIONS #if defined(DEBUG_DRAW_INTERSECTIONS) RenderManager::Instance()->SetColor(0.0f, 1.0f, 0.0f, 1.0f); RenderHelper::DrawLine(ray0, ray1); #endif for (int i = 0; i < pointCount; ++i) { int32 i2 = (i == pointCount - 1) ? (0) : (i + 1); Vector2 pt1(points[i].x, points[i].y); Vector2 pt2(points[i2].x, points[i2].y); Vector2 result; if (Collisions::Instance()->IsSegmentIntersectsSegment(pt1, pt2, ray0, ray1, result)) { #if defined(DEBUG_DRAW_INTERSECTIONS) RenderManager::Instance()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); RenderHelper::DrawPoint(result, 5.0f); #endif intersectionsCount++; } } return intersectionsCount & 1; }
int main(int argc, char *argv[]) { Vector orig(0,0,0); double radius = 1; Ray ray1(Vector(-2, 1, 0), Vector(1,0,0)); Ray ray2(Vector(-2, 1, 0), Vector(-1,0,0)); Ray ray3(Vector(0, 0.5f, 0), Vector(1,0,0)); Sphere sphere(orig, radius); ASSERT(sphere.intersect(ray1), true, "No intersection"); ASSERT(sphere.intersect(ray2), false, "Error in intersection"); ASSERT(sphere.intersect(ray3), false, "Origin is inside the Sphere"); REPORT(); return ERROR_COUNT; }
TEST(CubeTest, FindIntersection) { Cube cube; double t; Point3 point; Vector3 normal; Ray ray1(Point3(0, 0, 2), Vector3(0, 0, -1)); EXPECT_TRUE(cube.FindIntersection(ray1, &t, &point, &normal)); EXPECT_EQ(1, t); EXPECT_EQ(0, point[0]); EXPECT_EQ(0, point[1]); EXPECT_EQ(1, point[2]); EXPECT_EQ(0, normal[0]); EXPECT_EQ(0, normal[1]); EXPECT_EQ(1, normal[2]); Ray ray2(Point3(0, 0, 2), Vector3(0, 0, 1)); EXPECT_FALSE(cube.FindIntersection(ray2, &t, &point, &normal)); }
void tst_QRay3D::transform() { QFETCH(QVector3D, point); QFETCH(QVector3D, direction); QMatrix4x4 m; m.translate(-1.0f, 2.5f, 5.0f); m.rotate(45.0f, 1.0f, 1.0f, 1.0f); m.scale(23.5f); Qt3DRender::RayCasting::QRay3D ray1(point, direction); Qt3DRender::RayCasting::QRay3D ray2(ray1); Qt3DRender::RayCasting::QRay3D ray3; ray1.transform(m); ray3 = ray2.transformed(m); QVERIFY(fuzzyCompare(ray1.origin(), ray3.origin())); QVERIFY(fuzzyCompare(ray1.direction(), ray3.direction())); QVERIFY(fuzzyCompare(ray1.origin(), m * point)); QVERIFY(fuzzyCompare(ray1.direction(), m.mapVector(direction))); }
void tst_QRay3D::transform() { QFETCH(QVector3D, point); QFETCH(QVector3D, direction); QMatrix4x4 m; m.translate(-1.0f, 2.5f, 5.0f); m.rotate(45.0f, 1.0f, 1.0f, 1.0f); m.scale(23.5f); QRay3D ray1(point, direction); QRay3D ray2(ray1); QRay3D ray3; ray1.transform(m); ray3 = ray2.transformed(m); QCOMPARE(ray1.origin(), ray3.origin()); QCOMPARE(ray1.direction(), ray3.direction()); QCOMPARE(ray1.origin(), m * point); QCOMPARE(ray1.direction(), m.mapVector(direction)); }
bool smooth_curve(const BVH *bvh, const VectorXu &E2E, std::vector<CurvePoint> &curve, bool watertight) { const MatrixXu &F = *bvh->F(); const MatrixXf &V = *bvh->V(), &N = *bvh->N(); cout << endl; std::vector<CurvePoint> curve_new; std::vector<Float> weight; std::vector<uint32_t> path; cout << "Input: " << curve.size() << " vertices" << endl; for (int it=0;; ++it) { if (curve.size() < 2) return false; for (uint32_t it2=0; it2<curve.size(); ++it2) { curve_new.clear(); curve_new.push_back(curve[0]); for (uint32_t i=1; i<curve.size()-1; ++i) { Vector3f p_new = 0.5f * (curve[i-1].p + curve[i+1].p); Vector3f n_new = (curve[i-1].n + curve[i+1].n).normalized(); Float maxlength = (curve[i-1].p - curve[i+1].p).norm()*2; Ray ray1(p_new, n_new, 0, maxlength); Ray ray2(p_new, -n_new, 0, maxlength); uint32_t idx1 = 0, idx2 = 0; Float t1 = 0, t2 = 0; Vector2f uv1, uv2; bool hit1 = bvh->rayIntersect(ray1, idx1, t1, &uv1); bool hit2 = bvh->rayIntersect(ray2, idx2, t2, &uv2); if (!hit1 && !hit2) continue; CurvePoint pt; if (t1 < t2) { pt.p = ray1(t1); pt.f = idx1; pt.n = ((1 - uv1.sum()) * N.col(F(0, idx1)) + uv1.x() * N.col(F(1, idx1)) + uv1.y() * N.col(F(2, idx1))).normalized(); } else { pt.p = ray2(t2); pt.f = idx2; pt.n = ((1 - uv2.sum()) * N.col(F(0, idx2)) + uv2.x() * N.col(F(1, idx2)) + uv2.y() * N.col(F(2, idx2))).normalized(); } curve_new.push_back(pt); } curve_new.push_back(curve[curve.size()-1]); curve.swap(curve_new); } if (!watertight && it == 1) break; curve_new.clear(); curve_new.push_back(curve[0]); for (uint32_t i=1; i<curve.size(); ++i) { if (!astar(F, E2E, V, curve[i-1].f, curve[i].f, path)) return false; auto closest = [](const Vector3f &p0, const Vector3f &p1, const Vector3f &target) -> Vector3f { Vector3f d = (p1-p0).normalized(); return p0 + d * std::min(std::max((target-p0).dot(d), 0.0f), (p0-p1).norm()); }; if (path.size() > 2) { uint32_t base = curve_new.size() - 1; for (uint32_t j=1; j<path.size()-1; ++j) { uint32_t f = path[j]; Vector3f p0 = V.col(F(0, f)), p1 = V.col(F(1, f)), p2 = V.col(F(2, f)); CurvePoint pt2; pt2.f = f; pt2.n = (p1-p0).cross(p2-p0).normalized(); pt2.p = (p0+p1+p2) * (1.0f / 3.0f); curve_new.push_back(pt2); } curve_new.push_back(curve[i]); for (uint32_t q=1; q<path.size()-1; ++q) { for (uint32_t j=1; j<path.size()-1; ++j) { Float bestDist1 = std::numeric_limits<Float>::infinity(); Float bestDist2 = std::numeric_limits<Float>::infinity(); Vector3f bestPt1 = Vector3f::Zero(), bestPt2 = Vector3f::Zero(); uint32_t f = path[j]; for (uint32_t k=0; k<3; ++k) { Vector3f closest1 = closest(V.col(F(k, f)), V.col(F((k + 1) % 3, f)), curve_new[base+j-1].p); Vector3f closest2 = closest(V.col(F(k, f)), V.col(F((k + 1) % 3, f)), curve_new[base+j+1].p); Float dist1 = (closest1 - curve_new[base+j-1].p).norm(); Float dist2 = (closest2 - curve_new[base+j+1].p).norm(); if (dist1 < bestDist1) { bestDist1 = dist1; bestPt1 = closest1; } if (dist2 < bestDist2) { bestDist2 = dist2; bestPt2 = closest2; } } curve_new[base+j].p = (bestPt1 + bestPt2) * 0.5f; } } } else { curve_new.push_back(curve[i]); } } curve.swap(curve_new); curve_new.clear(); curve_new.push_back(curve[0]); weight.clear(); weight.push_back(1.0f); for (uint32_t i=0; i<curve.size(); ++i) { auto &cur = curve_new[curve_new.size()-1]; auto &cur_weight = weight[weight.size()-1]; if (cur.f == curve[i].f) { cur.p += curve[i].p; cur.n += curve[i].n; cur_weight += 1; } else { curve_new.push_back(curve[i]); weight.push_back(1.f); } } for (uint32_t i=0; i<curve_new.size(); ++i) { curve_new[i].p /= weight[i]; curve_new[i].n.normalize(); } curve_new[0] = curve[0]; curve_new[curve_new.size()-1] = curve[curve.size()-1]; if (curve_new.size() < 2 || curve_new[0].f == curve_new[curve_new.size()-1].f) return false; curve_new.swap(curve); if (it > 2) break; } cout << "Smoothed curve: " << curve.size() << " vertices" << endl; return true; }
void LPESimplify::generateHelperPathAndSmooth(Geom::PathVector &result) { if(steps < 1) { return; } Geom::PathVector tmp_path; Geom::CubicBezier const *cubic = NULL; for (Geom::PathVector::iterator path_it = result.begin(); path_it != result.end(); ++path_it) { if (path_it->empty()) { continue; } Geom::Path::iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::iterator curve_it2 = ++(path_it->begin());// outgoing curve Geom::Path::iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop SPCurve *nCurve = new SPCurve(); if (path_it->closed()) { // if the path is closed, maybe we have to stop a bit earlier because the // closing line segment has zerolength. const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type // Geom::LineSegment. if (are_near(closingline.initialPoint(), closingline.finalPoint())) { // closingline.isDegenerate() did not work, because it only checks for // *exact* zero length, which goes wrong for relative coordinates and // rounding errors... // the closing line segment has zero-length. So stop before that one! curve_endit = path_it->end_open(); } } if(helper_size > 0) { drawNode(curve_it1->initialPoint()); } nCurve->moveto(curve_it1->initialPoint()); Geom::Point start = Geom::Point(0,0); while (curve_it1 != curve_endit) { cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1); Geom::Point point_at1 = curve_it1->initialPoint(); Geom::Point point_at2 = curve_it1->finalPoint(); Geom::Point point_at3 = curve_it1->finalPoint(); Geom::Point point_at4 = curve_it1->finalPoint(); if(start == Geom::Point(0,0)) { start = point_at1; } if (cubic) { point_at1 = (*cubic)[1]; point_at2 = (*cubic)[2]; } if(path_it->closed() && curve_it2 == curve_endit) { point_at4 = start; } if(curve_it2 != curve_endit) { cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2); if (cubic) { point_at4 = (*cubic)[1]; } } Geom::Ray ray1(point_at2, point_at3); Geom::Ray ray2(point_at3, point_at4); double angle1 = Geom::deg_from_rad(ray1.angle()); double angle2 = Geom::deg_from_rad(ray2.angle()); if((smooth_angles >= std::abs(angle2 - angle1)) && !are_near(point_at4,point_at3) && !are_near(point_at2,point_at3)) { double dist = Geom::distance(point_at2,point_at3); Geom::Angle angleFixed = ray2.angle(); angleFixed -= Geom::Angle::from_degrees(180.0); point_at2 = Geom::Point::polar(angleFixed, dist) + point_at3; } nCurve->curveto(point_at1, point_at2, curve_it1->finalPoint()); cubic = dynamic_cast<Geom::CubicBezier const *>(nCurve->last_segment()); if (cubic) { point_at1 = (*cubic)[1]; point_at2 = (*cubic)[2]; if(helper_size > 0) { if(!are_near((*cubic)[0],(*cubic)[1])) { drawHandle((*cubic)[1]); drawHandleLine((*cubic)[0],(*cubic)[1]); } if(!are_near((*cubic)[3],(*cubic)[2])) { drawHandle((*cubic)[2]); drawHandleLine((*cubic)[3],(*cubic)[2]); } } } if(helper_size > 0) { drawNode(curve_it1->finalPoint()); } ++curve_it1; ++curve_it2; } if (path_it->closed()) { nCurve->closepath_current(); } tmp_path.push_back(nCurve->get_pathvector()[0]); nCurve->reset(); delete nCurve; } result = tmp_path; }