Repository navigation
Conversation
Replaces the sketcher's SciPy-based solver with the raygeo sketch module (barebaric/raygeo#117, #118). The Solver keeps its public contract (constructor, solve(), get_conflicting_constraints(), CONFLICT_ERROR_THRESHOLD) and becomes a thin bridge: it flattens the registry and constraints into a raygeo problem, runs the Rust trust-region solve, and writes positions, per-point constrained flags and conflict indices back to the Python model. Each constraint provides the mapping through a new polymorphic to_solver_constraint(registry) method, which resolves entity references to concrete point ids and hands the already-evaluated dimensional values to the matching raygeo.sketch.constraints class. Constraints without a solver counterpart (missing or unsupported operands) are skipped, and the returned conflict indices are mapped back to the sketch's constraint list. The scipy least_squares loop, its BLAS thread limiting and the numpy/scipy state vector plumbing are gone from the sketcher; the old _solve_decomposed/_solve_scoped machinery now lives in raygeo.sketch.Solver, which also exposes status()/nfev() for the solver debug log. Two solver-internal partition tests are rewritten against the public API: the partitioning itself moved into raygeo (covered by raygeo's own tests), and the remaining observable behavior — islands solving independently and bridged islands solving as one — is asserted through solve(). The separated-islands assertion now checks the satisfied distance rather than a fixed position, since a single distance constraint alone admits two mirrored solutions and the solver legitimately picks the nearest one. Requires raygeo 1.77.0 (release pending; contains raygeo#117 and #118). Differential parity against the SciPy solver was verified on nine representative problems (success flags, positions, DOF flags and conflict sets) before the swap.
The sketcher entities stop hand-rolling geometry that raygeo (barebaric/raygeo#119) now provides: - Arc.tangent_at uses get_arc_tangent_at_point (chirality-signed unit tangent); Arc.signed_distance_to and Circle.signed_distance_to use get_circle_signed_distance; Arc.to_polygon_vertices and preview_polylines sample via get_arc_samples/get_arc_sweep instead of manual sweep normalization and trig loops - Bezier.tangent_at evaluates the derivative via get_bezier_tangent (direction-identical; consumers only use the angle), and the private _sample_bezier is replaced by get_bezier_samples across hit testing, bbox computation, rect intersection and polygon assembly - Ellipse.hit_test, contains_point and preview_polylines delegate to is_point_on_ellipse, is_point_inside_ellipse and get_ellipse_samples - Point._compute_constrained_cp delegates to compute_constrained_control_offset The sampling policies (segment counts, tolerance scaling) stay in the entities; only the geometric kernels moved. Entity tests that exercised the removed private sampler are ported onto its public replacement.
The constraint facades' draw methods now delegate to the raygeo solver constraint's draw, which replays the reference symbol geometry, colors and underlays onto the caller's cairo context. The base class mirrors the registry's points and the line/text-box entities the symbols consult into a raygeo registry, and forwards the constraint's status ordinal so hover/conflict/expression colors keep working. Labels are rendered through the raygeo text stack (status-colored background box sized from the font metrics, glyphs stroked as outlines) instead of Pango layouts; the constraint text rendering tests now pin the label box geometry against raygeo's text metrics, and the distance draw test keeps its real-surface pixel check.
raygeo's constraint draw now reads the document through its DrawContext protocol, so the facades hand the registry over through a SolverDrawContext adapter instead of mirroring points and entities into a throwaway raygeo registry on every draw call. Positions the symbols draw stay live with the document at all times.
The solver constraints' surface is the raygeo SolverConstraint protocol; the fifteen drawable constraints pull the typed _draw_solver_constraint helper in through a SolverDrawConstraint mixin so the base class keeps its wide to_solver_constraint type without loosening anything to Any. The draw context adapter's parameter names match the protocol keywords.
Replace the sketcher entity/constraint facade packages with raygeo's document model: the registry re-exports raygeo's EntityRegistry, Sketch delegates points/entities/constraints to it, and a legacy migration shim loads old .ryp sketches. Commands, tools, selection and renderer use the raygeo classes directly. Deletes sketcher/core/entities and sketcher/core/constraints.
…ls, removed-points view
…ne points, identity by id
…, skip default waypoints
…a, final test fixes
- Renderer junction overlay: _safe_get_point now returns a plain tuple as its annotation promises; the live point object crashed the GTK snapshot transform. - Ellipse/circle creation: the temp start point is removed again after the commit (as on main) instead of being adopted into the command, so no stray standalone dot is left at the press corner. The temp-start test now pins the removal. - Waypoint tools: call sketch.registry.entities() — the bare attribute crashed the right-click pie menu. - Typing: central Entity/Constraint/HitTarget aliases in core.types; ~250 Any annotations across the addon replaced with precise types (remaining Anys are dict[str, Any] serialization payloads only).
raygeo 1.78.1 gives the document model nominal Python types: every constraint class extends Constraint, every entity class Entity. The sketcher drops its local type unions — annotations import the nominal types straight from raygeo, sketcher/core/types.py shrinks to EntityID and the UI-only HitTarget alias, and the array guide-frame annotations reflect the live point views. Verified against the published 1.78.1 wheel.
entity_ops imports nothing internal at module level, so the local imports of it (and of raygeo classes, and of constraint_info) in offset, items, fillet, chamfer, rectangle, text_property, equal_constraint and entity_flags had no cycle to break — they move to the module imports. The remaining function-level imports in sketch.py break documented import cycles and stay.
raygeo 1.78.2 publishes EntityID with the registry API annotated in it — the model's id space is raygeo-owned, so the sketcher imports the alias from raygeo instead of defining it locally. sketcher/core/types.py now contains only the UI-level HitTarget alias.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Moves the sketcher core onto raygeo in four phases — the document model included:
1. Solver
sketcher/core/solver.pyis a façade overraygeo.sketch.Solver(the Rust port of the scipy trust-region-reflective least-squares solver). The façade flattens the registry intoPointDefs, solves, and maps positions and constrained flags back. Global solves partition into independent components and solve each island; conflicting-constraint detection maps raygeo indices back to constraint positions.2. Entity math
Entity geometry/queries delegate to the raygeo shape helpers (line/arc/circle/ellipse/bezier/polygon), replacing hand-rolled Python math with calls into
raygeo.geo.shape.*.3. Constraint drawing
Constraint drawing delegates to the raygeo solver constraint's
draw: the same symbol geometry, status colors, selection/conflict underlays and label layout, replayed onto the caller's cairo context. Labels render through the raygeo text stack (status-colored box sized from font metrics, glyphs stroked astext_to_geometryoutlines) instead of Pango layouts, keeping raygeo GUI-toolkit-free.4. Document model
raygeo owns the model and its serialization. The
sketcher/core/entities/andconstraints/façade packages are deleted — rayforge imports raygeo's entity, constraint and registry classes directly:Sketchholds the raygeoEntityRegistry; constraints are raygeo value objects over resolved point ids, with reference metadata (entity_ids,shape_id, expressions) carried alongside for the UI and lossless serialization..rypmigration); constraint dicts are stored verbatim so save/reload preserves references, expressions andnullkeys.Dependency
Pins
raygeo==1.78.2(PyPI wheels + sdist, crates published),pixi.lockre-locked. The document model now owns its Python vocabulary: 1.78.1 added the nominalConstraint/Entitybase types and 1.78.2 the registry-ownedEntityID(annotated across the whole registry API in the generated stubs). The sketcher imports all three straight from raygeo;sketcher/core/types.pyshrinks to the UI-levelHitTargetalias alone. The suite below was run against the published wheel, not just the local checkout.Tests
get_pointresults) inherited from the migration's API surface; tests and the other linters are green, tracked as follow-up.Follow-up
None blocking. The sketcher now runs entirely on raygeo's model; the remaining
typings/stub surface and the pyright backlog are incremental cleanup.