mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 14:15:53 +08:00
Add allignable inner support island point
This commit is contained in:
parent
10c05ca01e
commit
0c9dedcffa
@ -257,8 +257,8 @@ double LineUtils::perp_distance(const Linef &line, Vec2d p)
|
|||||||
|
|
||||||
bool LineUtils::is_parallel(const Line &first, const Line &second)
|
bool LineUtils::is_parallel(const Line &first, const Line &second)
|
||||||
{
|
{
|
||||||
Point dir1 = first.b - first.a;
|
Point dir1 = direction(first);
|
||||||
Point dir2 = second.b - second.a;
|
Point dir2 = direction(second);
|
||||||
coord_t cross(
|
coord_t cross(
|
||||||
static_cast<int64_t>(dir1.x()) * dir2.y() -
|
static_cast<int64_t>(dir1.x()) * dir2.y() -
|
||||||
static_cast<int64_t>(dir2.x()) * dir1.y()
|
static_cast<int64_t>(dir2.x()) * dir1.y()
|
||||||
|
@ -853,16 +853,18 @@ void SampleIslandUtils::sample_field(VoronoiGraph::Position &field_start,
|
|||||||
Polygons polygons = offset(field.border, -2.f * config.minimal_distance_from_outline,
|
Polygons polygons = offset(field.border, -2.f * config.minimal_distance_from_outline,
|
||||||
ClipperLib::jtSquare);
|
ClipperLib::jtSquare);
|
||||||
if (polygons.empty()) return;
|
if (polygons.empty()) return;
|
||||||
ExPolygon inner(polygons.front());
|
|
||||||
|
auto inner = std::make_shared<ExPolygon>(polygons.front());
|
||||||
for (size_t i = 1; i < polygons.size(); ++i) {
|
for (size_t i = 1; i < polygons.size(); ++i) {
|
||||||
Polygon &hole = polygons[i];
|
Polygon &hole = polygons[i];
|
||||||
inner.holes.push_back(hole);
|
inner->holes.push_back(hole);
|
||||||
}
|
}
|
||||||
Points inner_points = sample_expolygon(inner, config.max_distance);
|
|
||||||
|
Points inner_points = sample_expolygon(*inner, config.max_distance);
|
||||||
std::transform(inner_points.begin(), inner_points.end(), std::back_inserter(points),
|
std::transform(inner_points.begin(), inner_points.end(), std::back_inserter(points),
|
||||||
[](const Point &point) {
|
[&](const Point &point) {
|
||||||
return std::make_unique<SupportIslandPoint>(
|
return std::make_unique<SupportIslandInnerPoint>(
|
||||||
point, SupportIslandPoint::Type::inner);
|
point, inner, SupportIslandPoint::Type::inner);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1231,11 +1233,14 @@ SampleIslandUtils::outline_offset(const Slic3r::ExPolygon &island,
|
|||||||
std::map<size_t, size_t> converter;
|
std::map<size_t, size_t> converter;
|
||||||
for (size_t island_line_index = 0; island_line_index < island_lines.size(); ++island_line_index) {
|
for (size_t island_line_index = 0; island_line_index < island_lines.size(); ++island_line_index) {
|
||||||
const Line &island_line = island_lines[island_line_index];
|
const Line &island_line = island_lines[island_line_index];
|
||||||
Vec2f dir1 = LineUtils::direction(island_line).cast<float>();
|
Vec2d dir1 = LineUtils::direction(island_line).cast<double>();
|
||||||
|
dir1.normalize();
|
||||||
for (size_t offset_line_index = 0; offset_line_index < offset_lines.size(); ++offset_line_index) {
|
for (size_t offset_line_index = 0; offset_line_index < offset_lines.size(); ++offset_line_index) {
|
||||||
const Line &offset_line = offset_lines[offset_line_index];
|
const Line &offset_line = offset_lines[offset_line_index];
|
||||||
Vec2f dir2 = LineUtils::direction(offset_line).cast<float>();
|
Vec2d dir2 = LineUtils::direction(offset_line).cast<double>();
|
||||||
if (fabs(dir1.dot(dir2)) < 1e-4) { // in similar direction
|
dir2.normalize();
|
||||||
|
double angle = acos(dir1.dot(dir2));
|
||||||
|
if (fabs(angle) < 1e-4) { // in similar direction
|
||||||
Point middle = offset_line.a / 2 + offset_line.b / 2;
|
Point middle = offset_line.a / 2 + offset_line.b / 2;
|
||||||
double distance = island_line.perp_distance_to(middle);
|
double distance = island_line.perp_distance_to(middle);
|
||||||
if (fabs(distance - offset_distance) < 20) {
|
if (fabs(distance - offset_distance) < 20) {
|
||||||
@ -1309,16 +1314,17 @@ SupportIslandPoints SampleIslandUtils::sample_outline(
|
|||||||
auto add_lines_samples = [&](const Lines &inner_lines,
|
auto add_lines_samples = [&](const Lines &inner_lines,
|
||||||
size_t first_index,
|
size_t first_index,
|
||||||
size_t last_index) {
|
size_t last_index) {
|
||||||
|
++last_index; // index after last item
|
||||||
Lines lines;
|
Lines lines;
|
||||||
// is over start ?
|
// is over start ?
|
||||||
if (first_index > last_index) {
|
if (first_index > last_index) {
|
||||||
size_t count = first_index + inner_lines.size() - last_index;
|
size_t count = last_index + (inner_lines.size() - first_index);
|
||||||
lines.reserve(count);
|
lines.reserve(count);
|
||||||
std::copy(inner_lines.begin() + last_index,
|
std::copy(inner_lines.begin() + first_index,
|
||||||
inner_lines.end(),
|
inner_lines.end(),
|
||||||
std::back_inserter(lines));
|
std::back_inserter(lines));
|
||||||
std::copy(inner_lines.begin(),
|
std::copy(inner_lines.begin(),
|
||||||
inner_lines.begin() + first_index,
|
inner_lines.begin() + last_index,
|
||||||
std::back_inserter(lines));
|
std::back_inserter(lines));
|
||||||
} else {
|
} else {
|
||||||
size_t count = last_index - first_index;
|
size_t count = last_index - first_index;
|
||||||
@ -1376,8 +1382,11 @@ SupportIslandPoints SampleIslandUtils::sample_outline(
|
|||||||
// first and last index to inner lines
|
// first and last index to inner lines
|
||||||
size_t inner_first = inner_invalid;
|
size_t inner_first = inner_invalid;
|
||||||
size_t inner_last = inner_invalid;
|
size_t inner_last = inner_invalid;
|
||||||
|
size_t stop_index = first_change_index;
|
||||||
|
if (stop_index == 0)
|
||||||
|
stop_index = polygon.size();
|
||||||
for (size_t polygon_index = first_change_index + 1;
|
for (size_t polygon_index = first_change_index + 1;
|
||||||
polygon_index != first_change_index; ++polygon_index) {
|
polygon_index != stop_index; ++polygon_index) {
|
||||||
if (polygon_index == polygon.size()) polygon_index = 0;
|
if (polygon_index == polygon.size()) polygon_index = 0;
|
||||||
size_t index = polygon_index + index_offset;
|
size_t index = polygon_index + index_offset;
|
||||||
assert(index < field.source_indexes.size());
|
assert(index < field.source_indexes.size());
|
||||||
@ -1390,7 +1399,7 @@ SupportIslandPoints SampleIslandUtils::sample_outline(
|
|||||||
inner_last = inner_invalid;
|
inner_last = inner_invalid;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto convert_index_item = field_2_inner.find(polygon_index);
|
auto convert_index_item = field_2_inner.find(index);
|
||||||
// check if exist inner line
|
// check if exist inner line
|
||||||
if (convert_index_item == field_2_inner.end()) continue;
|
if (convert_index_item == field_2_inner.end()) continue;
|
||||||
inner_last = convert_index_item->second - index_offset;
|
inner_last = convert_index_item->second - index_offset;
|
||||||
|
@ -145,10 +145,11 @@ SupportOutlineIslandPoint::MoveResult SupportOutlineIslandPoint::create_result(
|
|||||||
const Line &line = restriction->lines[index];
|
const Line &line = restriction->lines[index];
|
||||||
double line_ratio_full = LineUtils::foot(line, destination);
|
double line_ratio_full = LineUtils::foot(line, destination);
|
||||||
double line_ratio = std::clamp(line_ratio_full, 0., 1.);
|
double line_ratio = std::clamp(line_ratio_full, 0., 1.);
|
||||||
Position new_position(index, line_ratio);
|
Position position(index, line_ratio);
|
||||||
Point new_point = calc_point(new_position, *restriction);
|
Point point = calc_point(position, *restriction);
|
||||||
double point_distance = (new_point - destination).cast<double>().norm();
|
double distance_double = (point - destination).cast<double>().norm();
|
||||||
return MoveResult(new_position, new_point, point_distance);
|
coord_t distance = static_cast<coord_t>(distance_double);
|
||||||
|
return MoveResult(position, point, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SupportOutlineIslandPoint::update_result(MoveResult & result,
|
void SupportOutlineIslandPoint::update_result(MoveResult & result,
|
||||||
@ -158,15 +159,61 @@ void SupportOutlineIslandPoint::update_result(MoveResult & result,
|
|||||||
const Line &line = restriction->lines[index];
|
const Line &line = restriction->lines[index];
|
||||||
double line_ratio_full = LineUtils::foot(line, destination);
|
double line_ratio_full = LineUtils::foot(line, destination);
|
||||||
double line_ratio = std::clamp(line_ratio_full, 0., 1.);
|
double line_ratio = std::clamp(line_ratio_full, 0., 1.);
|
||||||
Position new_position(index, line_ratio);
|
Position position(index, line_ratio);
|
||||||
Point new_point = calc_point(new_position, *restriction);
|
Point point = calc_point(position, *restriction);
|
||||||
Point diff = new_point - destination;
|
Point diff = point - destination;
|
||||||
if (abs(diff.x()) > result.distance) return;
|
if (abs(diff.x()) > result.distance) return;
|
||||||
if (abs(diff.y()) > result.distance) return;
|
if (abs(diff.y()) > result.distance) return;
|
||||||
double point_distance = diff.cast<double>().norm();
|
double distance_double = diff.cast<double>().norm();
|
||||||
if (result.distance > point_distance) {
|
coord_t distance = static_cast<coord_t>(distance_double);
|
||||||
result.distance = point_distance;
|
if (result.distance > distance) {
|
||||||
result.position = new_position;
|
result.distance = distance;
|
||||||
result.point = new_point;
|
result.position = position;
|
||||||
|
result.point = point;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
/// Inner Point
|
||||||
|
///////////////////////
|
||||||
|
|
||||||
|
SupportIslandInnerPoint::SupportIslandInnerPoint(
|
||||||
|
Point point, std::shared_ptr<ExPolygon> inner, Type type)
|
||||||
|
: SupportIslandPoint(point, type), inner(std::move(inner))
|
||||||
|
{}
|
||||||
|
|
||||||
|
coord_t SupportIslandInnerPoint::move(const Point &destination) {
|
||||||
|
|
||||||
|
// IMPROVE: Do not move over island hole if there is no connected island.
|
||||||
|
// Can cause bad supported area in very special case.
|
||||||
|
|
||||||
|
if (inner->contains(destination))
|
||||||
|
return SupportIslandPoint::move(destination);
|
||||||
|
|
||||||
|
// find closest line cross area border
|
||||||
|
Vec2d v1 = (destination-point).cast<double>();
|
||||||
|
double closest_ratio = 1.;
|
||||||
|
Lines lines = to_lines(*inner);
|
||||||
|
for (const Line &line : lines) {
|
||||||
|
// line intersection
|
||||||
|
const Vec2d v2 = LineUtils::direction(line).cast<double>();
|
||||||
|
double denom = cross2(v1, v2);
|
||||||
|
// is line parallel
|
||||||
|
if (fabs(denom) < std::numeric_limits<float>::epsilon()) continue;
|
||||||
|
|
||||||
|
const Vec2d v12 = (point - line.a).cast<double>();
|
||||||
|
double nume1 = cross2(v2, v12);
|
||||||
|
double t1 = nume1 / denom;
|
||||||
|
if (t1 < 0. || t1 > closest_ratio) continue; // out of line
|
||||||
|
|
||||||
|
double nume2 = cross2(v1, v12);
|
||||||
|
double t2 = nume2 / denom;
|
||||||
|
if (t2 < 0. || t2 > 1.0) continue; // out of contour
|
||||||
|
|
||||||
|
closest_ratio = t1;
|
||||||
|
}
|
||||||
|
// no correct closest point --> almost parallel cross
|
||||||
|
if (closest_ratio >= 1.) return 0;
|
||||||
|
Point new_point = point + (closest_ratio * v1).cast<coord_t>();
|
||||||
|
return SupportIslandPoint::move(new_point);
|
||||||
|
}
|
@ -83,6 +83,30 @@ public:
|
|||||||
using SupportIslandPointPtr = std::unique_ptr<SupportIslandPoint>;
|
using SupportIslandPointPtr = std::unique_ptr<SupportIslandPoint>;
|
||||||
using SupportIslandPoints = std::vector<SupportIslandPointPtr>;
|
using SupportIslandPoints = std::vector<SupportIslandPointPtr>;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Support point with no move during aligning
|
||||||
|
/// </summary>
|
||||||
|
class SupportIslandNoMovePoint : public SupportIslandPoint
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//constructor
|
||||||
|
using SupportIslandPoint::SupportIslandPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can move?
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>FALSE</returns>
|
||||||
|
virtual bool can_move() const override { return false; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// No move!
|
||||||
|
/// Should not be call.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">Wanted position</param>
|
||||||
|
/// <returns>No move means zero distance</returns>
|
||||||
|
virtual coord_t move(const Point &destination) { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DTO Support point laying on voronoi graph edge
|
/// DTO Support point laying on voronoi graph edge
|
||||||
/// Restriction to move only on Voronoi graph
|
/// Restriction to move only on Voronoi graph
|
||||||
@ -250,9 +274,9 @@ private:
|
|||||||
// point laying on restricted line
|
// point laying on restricted line
|
||||||
Point point;
|
Point point;
|
||||||
// distance point on restricted line from destination point
|
// distance point on restricted line from destination point
|
||||||
double distance;
|
coord_t distance;
|
||||||
|
|
||||||
MoveResult(Position position, Point point, double distance)
|
MoveResult(Position position, Point point, coord_t distance)
|
||||||
: position(position), point(point), distance(distance)
|
: position(position), point(point), distance(distance)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@ -260,5 +284,30 @@ private:
|
|||||||
void update_result(MoveResult& result, size_t index, const Point &destination);
|
void update_result(MoveResult& result, size_t index, const Point &destination);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store pointer to inner ExPolygon for allowed move across island area
|
||||||
|
/// Give an option to move with point
|
||||||
|
/// </summary>
|
||||||
|
class SupportIslandInnerPoint: public SupportIslandPoint
|
||||||
|
{
|
||||||
|
// define inner area of island where inner point could move during aligning
|
||||||
|
std::shared_ptr<ExPolygon> inner;
|
||||||
|
public:
|
||||||
|
SupportIslandInnerPoint(Point point,
|
||||||
|
std::shared_ptr<ExPolygon> inner,
|
||||||
|
Type type = Type::inner);
|
||||||
|
|
||||||
|
bool can_move() const override { return true; };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Move nearest to destination point
|
||||||
|
/// only inside inner area
|
||||||
|
/// + change current position
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination">Wanted support position</param>
|
||||||
|
/// <returns>move distance euclidean</returns>
|
||||||
|
coord_t move(const Point &destination) override;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Slic3r::sla
|
} // namespace Slic3r::sla
|
||||||
#endif // slic3r_SLA_SuppotstIslands_SupportIslandPoint_hpp_
|
#endif // slic3r_SLA_SuppotstIslands_SupportIslandPoint_hpp_
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace Slic3r::sla;
|
using namespace Slic3r::sla;
|
||||||
|
|
||||||
//#define STORE_SAMPLE_INTO_SVG_FILES
|
#define STORE_SAMPLE_INTO_SVG_FILES
|
||||||
|
|
||||||
TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
||||||
|
|
||||||
@ -273,17 +273,40 @@ ExPolygon create_tiny_wide_test_2(double wide, double tiny)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons createTestIslands(double size)
|
ExPolygon create_tiny_between_holes(double wide, double tiny)
|
||||||
{
|
{
|
||||||
bool useFrogLeg = false;
|
double hole_size = wide;
|
||||||
// need post reorganization of longest path
|
double width = 2 * wide + 2*hole_size + tiny;
|
||||||
ExPolygon mountains({{0., 0.},
|
double height = 2 * wide + hole_size;
|
||||||
|
auto outline = PolygonUtils::create_rect(width, height);
|
||||||
|
auto holeL = PolygonUtils::create_rect(hole_size, hole_size);
|
||||||
|
holeL.reverse();
|
||||||
|
auto holeR = holeL;
|
||||||
|
int hole_move_x = (hole_size + tiny)/2;
|
||||||
|
holeL.translate(-hole_move_x, 0);
|
||||||
|
holeR.translate(hole_move_x, 0);
|
||||||
|
|
||||||
|
ExPolygon result(outline);
|
||||||
|
result.holes = {holeL, holeR};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stress test for longest path
|
||||||
|
// needs reshape
|
||||||
|
ExPolygon create_mountains(double size) {
|
||||||
|
return ExPolygon({{0., 0.},
|
||||||
{size, 0.},
|
{size, 0.},
|
||||||
{5 * size / 6, size},
|
{5 * size / 6, size},
|
||||||
{4 * size / 6, size / 6},
|
{4 * size / 6, size / 6},
|
||||||
{3 * size / 7, 2 * size},
|
{3 * size / 7, 2 * size},
|
||||||
{2 * size / 7, size / 6},
|
{2 * size / 7, size / 6},
|
||||||
{size / 7, size}});
|
{size / 7, size}});
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygons createTestIslands(double size)
|
||||||
|
{
|
||||||
|
bool useFrogLeg = false;
|
||||||
|
// need post reorganization of longest path
|
||||||
ExPolygons result = {
|
ExPolygons result = {
|
||||||
// one support point
|
// one support point
|
||||||
ExPolygon(PolygonUtils::create_equilateral_triangle(size)),
|
ExPolygon(PolygonUtils::create_equilateral_triangle(size)),
|
||||||
@ -311,13 +334,14 @@ ExPolygons createTestIslands(double size)
|
|||||||
ExPolygon(PolygonUtils::create_isosceles_triangle(5. * size, 40. * size)),
|
ExPolygon(PolygonUtils::create_isosceles_triangle(5. * size, 40. * size)),
|
||||||
create_tiny_wide_test_1(3 * size, 2 / 3. * size),
|
create_tiny_wide_test_1(3 * size, 2 / 3. * size),
|
||||||
create_tiny_wide_test_2(3 * size, 2 / 3. * size),
|
create_tiny_wide_test_2(3 * size, 2 / 3. * size),
|
||||||
|
create_tiny_between_holes(3 * size, 2 / 3. * size),
|
||||||
|
|
||||||
// still problem
|
// still problem
|
||||||
// three support points
|
// three support points
|
||||||
ExPolygon(PolygonUtils::create_equilateral_triangle(3 * size)),
|
ExPolygon(PolygonUtils::create_equilateral_triangle(3 * size)),
|
||||||
ExPolygon(PolygonUtils::create_circle(size, 20)),
|
ExPolygon(PolygonUtils::create_circle(size, 20)),
|
||||||
|
|
||||||
mountains,
|
create_mountains(size),
|
||||||
create_trinagle_with_hole(size),
|
create_trinagle_with_hole(size),
|
||||||
create_square_with_hole(size, size / 2),
|
create_square_with_hole(size, size / 2),
|
||||||
create_square_with_hole(size, size / 3)
|
create_square_with_hole(size, size / 3)
|
||||||
@ -661,7 +685,7 @@ TEST_CASE("Compare sampling test", "[hide]")
|
|||||||
enum class Sampling {
|
enum class Sampling {
|
||||||
old,
|
old,
|
||||||
filip
|
filip
|
||||||
} sample_type = Sampling::filip;
|
} sample_type = Sampling::old;
|
||||||
|
|
||||||
std::function<std::vector<Vec2f>(const ExPolygon &)> sample =
|
std::function<std::vector<Vec2f>(const ExPolygon &)> sample =
|
||||||
(sample_type == Sampling::old) ? sample_old :
|
(sample_type == Sampling::old) ? sample_old :
|
||||||
@ -689,7 +713,7 @@ TEST_CASE("Compare sampling test", "[hide]")
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include <libslic3r/SLA/SupportIslands/VectorUtils.hpp>
|
#include <libslic3r/SLA/SupportIslands/VectorUtils.hpp>
|
||||||
TEST_CASE("Reorder destructive", "[hide]"){
|
TEST_CASE("Reorder destructive", "[Utils]"){
|
||||||
std::vector<int> data {0, 1, 3, 2, 4, 7, 6, 5, 8};
|
std::vector<int> data {0, 1, 3, 2, 4, 7, 6, 5, 8};
|
||||||
std::vector<int> order{0, 1, 3, 2, 4, 7, 6, 5, 8};
|
std::vector<int> order{0, 1, 3, 2, 4, 7, 6, 5, 8};
|
||||||
|
|
||||||
@ -699,6 +723,50 @@ TEST_CASE("Reorder destructive", "[hide]"){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <libslic3r/SLA/SupportIslands/LineUtils.hpp>
|
||||||
|
TEST_CASE("Intersection point", "[Utils]")
|
||||||
|
{
|
||||||
|
Point a1(0, 0);
|
||||||
|
Point b1(3, 6);
|
||||||
|
Line l1(a1, b1);
|
||||||
|
auto intersection = LineUtils::intersection(l1, Line(Point(0, 4), Point(5, 4)));
|
||||||
|
CHECK(intersection.has_value());
|
||||||
|
Point i_point = intersection->cast<coord_t>();
|
||||||
|
CHECK(PointUtils::is_equal(i_point, Point(2, 4)));
|
||||||
|
|
||||||
|
// same line
|
||||||
|
auto bad_intersection = LineUtils::intersection(l1, l1);
|
||||||
|
CHECK(!bad_intersection.has_value());
|
||||||
|
|
||||||
|
// oposit direction
|
||||||
|
bad_intersection = LineUtils::intersection(l1, Line(b1,a1));
|
||||||
|
CHECK(!bad_intersection.has_value());
|
||||||
|
|
||||||
|
// parallel line
|
||||||
|
bad_intersection = LineUtils::intersection(l1, Line(a1 + Point(0, 1),
|
||||||
|
b1 + Point(0, 1)));
|
||||||
|
CHECK(!bad_intersection.has_value());
|
||||||
|
|
||||||
|
// out of line segment, but ray has intersection
|
||||||
|
Line l2(Point(0, 8), Point(6, 8));
|
||||||
|
intersection = LineUtils::intersection(l1, l2);
|
||||||
|
auto intersection2 = LineUtils::intersection(l2, l1);
|
||||||
|
CHECK(intersection.has_value());
|
||||||
|
CHECK(intersection2.has_value());
|
||||||
|
i_point = intersection->cast<coord_t>();
|
||||||
|
CHECK(PointUtils::is_equal(i_point, Point(4, 8)));
|
||||||
|
CHECK(PointUtils::is_equal(i_point, intersection2->cast<coord_t>()));
|
||||||
|
|
||||||
|
Line l3(Point(-2, -2), Point(1, -2));
|
||||||
|
intersection = LineUtils::intersection(l1, l3);
|
||||||
|
intersection2 = LineUtils::intersection(l3, l1);
|
||||||
|
CHECK(intersection.has_value());
|
||||||
|
CHECK(intersection2.has_value());
|
||||||
|
i_point = intersection->cast<coord_t>();
|
||||||
|
CHECK(PointUtils::is_equal(i_point, Point(-1, -2)));
|
||||||
|
CHECK(PointUtils::is_equal(i_point, intersection2->cast<coord_t>()));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Disable visualization", "[hide]")
|
TEST_CASE("Disable visualization", "[hide]")
|
||||||
{
|
{
|
||||||
CHECK(true);
|
CHECK(true);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user