Files
OrcaSlicer/tests/libslic3r/test_sketchinference.cpp
T
Tommaso BianchiandClaude Opus 4.8 0f4060c0a9 Orca-Cad: port SnapOrca Design (parametric CAD tab) onto mainline OrcaSlicer
Grafts the sketch-first CAD environment from snaporca-cad onto the mainline
OrcaSlicer/OrcaSlicer base (vs snaporca's Snapmaker/OrcaSlicer base):
- 133 new files: CadDocument/SketchEngine/GeometryEngine/SketchConstraints/
  SketchSolver/SketchInference/ThreadStandards + vendored libslvs solver;
  DesignPanel/DesignCanvas/DesignSketchTool/SketchInlineEditor GUI; GLGizmo
  Primitive/Sketch; 75 design icons; Catch2 tests.
- Integration hooks ported to mainline's diverged versions: Design tab in
  MainFrame, embedded design viewport + sketch overlay + per-canvas chrome
  suppression in GLCanvas3D/PartPlate, gizmo registration, Plater accessors,
  CMake wiring (libslvs subdir, CAD sources, OCCT ModelingAlgorithms=ON).

Structural integration complete; build verification pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
2026-06-28 12:40:38 +02:00

78 lines
3.0 KiB
C++

#include <catch2/catch.hpp>
#include "libslic3r/SketchInference.hpp"
using namespace Slic3r;
using K = InferenceSnap::Kind;
static SketchEntity line(Vec2d a, Vec2d b)
{
SketchEntity e; e.type = SketchEntity::Type::Line; e.p0 = a; e.p1 = b; return e;
}
static SketchEntity circle(Vec2d c, double r)
{
SketchEntity e; e.type = SketchEntity::Type::Circle; e.center = c; e.p0 = c; e.radius = r; return e;
}
TEST_CASE("inference: cursor near a line endpoint snaps Coincident-able to it", "[inference]")
{
std::vector<SketchEntity> ents = { line({0, 0}, {10, 0}) };
auto s = infer_point_snap(ents, {10.3, 0.2}, 1.0);
REQUIRE(s.kind == K::Endpoint);
CHECK(s.entity == 0);
CHECK(s.role == SketchPointRole::P1);
CHECK((s.point - Vec2d(10, 0)).norm() == Approx(0.0).margin(1e-9));
}
TEST_CASE("inference: endpoint beats midpoint when both are in range", "[inference]")
{
std::vector<SketchEntity> ents = { line({0, 0}, {2, 0}) };
// Query equidistant-ish but closer to the endpoint: endpoint tier wins regardless.
auto s = infer_point_snap(ents, {1.9, 0.0}, 5.0);
CHECK(s.kind == K::Endpoint);
CHECK(s.role == SketchPointRole::P1);
}
TEST_CASE("inference: midpoint of a line is detected", "[inference]")
{
std::vector<SketchEntity> ents = { line({0, 0}, {10, 0}) };
auto s = infer_point_snap(ents, {5.1, 0.1}, 0.5, /*include_origin=*/false);
REQUIRE(s.kind == K::Midpoint);
CHECK((s.point - Vec2d(5, 0)).norm() == Approx(0.0).margin(1e-9));
}
TEST_CASE("inference: circle centre and rim", "[inference]")
{
std::vector<SketchEntity> ents = { circle({0, 0}, 5.0) };
auto c = infer_point_snap(ents, {0.2, 0.1}, 1.0, false);
CHECK(c.kind == K::Center);
auto r = infer_point_snap(ents, {5.1, 0.0}, 1.0, false);
REQUIRE(r.kind == K::OnEdge);
CHECK((r.point - Vec2d(5, 0)).norm() == Approx(0.0).margin(1e-9));
}
TEST_CASE("inference: origin snap when nothing else is near", "[inference]")
{
std::vector<SketchEntity> ents = { line({20, 20}, {30, 20}) };
auto s = infer_point_snap(ents, {0.1, 0.1}, 1.0);
REQUIRE(s.kind == K::Origin);
CHECK(s.entity == -1);
CHECK((s.point - Vec2d(0, 0)).norm() == Approx(0.0).margin(1e-9));
}
TEST_CASE("inference: nothing in range returns None and the raw query", "[inference]")
{
std::vector<SketchEntity> ents = { line({0, 0}, {10, 0}) };
auto s = infer_point_snap(ents, {50, 50}, 1.0, /*include_origin=*/false);
CHECK(s.kind == K::None);
CHECK((s.point - Vec2d(50, 50)).norm() == Approx(0.0).margin(1e-9));
}
TEST_CASE("inference: axis inference flags horizontal / vertical segments", "[inference]")
{
CHECK(infer_axis_constraint({0, 0}, {10, 0.05}).value() == SketchConstraintType::Horizontal);
CHECK(infer_axis_constraint({0, 0}, {0.05, 10}).value() == SketchConstraintType::Vertical);
CHECK_FALSE(infer_axis_constraint({0, 0}, {10, 10}).has_value()); // 45 deg
CHECK_FALSE(infer_axis_constraint({0, 0}, {0, 0}).has_value()); // degenerate
}