Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix bezier approximation #34

Merged
merged 1 commit into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions ocpsvg/ocp.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from OCP.BRepFeat import BRepFeat
from OCP.BRepLib import BRepLib_FindSurface
from OCP.BRepTools import BRepTools
from OCP.Convert import Convert_ParameterisationType
from OCP.GC import (
GC_MakeArcOfCircle,
GC_MakeArcOfEllipse,
Expand Down Expand Up @@ -357,7 +358,7 @@ def ellipse_curve(


def curve_to_bspline(curve: Geom_Curve) -> Geom_BSplineCurve:
return GeomConvert.CurveToBSplineCurve_s(curve) # type: ignore
return GeomConvert.CurveToBSplineCurve_s(curve, Convert_ParameterisationType.Convert_RationalC1) # type: ignore


def curve_to_beziers(
Expand Down Expand Up @@ -399,8 +400,10 @@ def curve_to_beziers(
)

else:
bspline = curve_to_bspline(curve)
bspline.Segment(adaptor.FirstParameter(), adaptor.LastParameter())
yield from bspline_to_beziers(
curve_to_bspline(curve),
bspline,
max_degree=max_degree,
max_segments=max_segments,
tolerance=tolerance,
Expand Down
2 changes: 2 additions & 0 deletions ocpsvg/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,8 @@ def curve_to_svg_path(
beziers = curve_to_beziers(
adaptor, tolerance=tolerance, max_degree=3 if use_cubics else 2
)
if reverse:
beziers = reversed(list(beziers))
for i, bezier in enumerate(beziers):
yield from bezier_to_svg_path(
bezier,
Expand Down
42 changes: 41 additions & 1 deletion tests/test_svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@

import pytest
import svgelements
from OCP.GC import GC_MakeArcOfCircle
from OCP.Geom import Geom_Circle, Geom_Curve, Geom_Ellipse, Geom_TrimmedCurve
from OCP.GeomAbs import GeomAbs_CurveType
from OCP.gp import gp_Pnt, gp_Vec
from OCP.gp import gp_Ax2, gp_Circ, gp_Pnt, gp_Vec
from OCP.TopoDS import TopoDS, TopoDS_Edge, TopoDS_Face, TopoDS_Shape, TopoDS_Wire
from pytest import approx, raises

Expand All @@ -33,6 +34,7 @@
SvgPathCommand,
_SegmentInPath, # type: ignore private usage
bezier_to_svg_path,
curve_to_svg_path,
edge_to_svg_path,
edges_from_svg_path,
face_to_svg_path,
Expand Down Expand Up @@ -159,6 +161,44 @@ def test_polyline_apprx(curve: Geom_Curve):
assert set(seg[0] for seg in path).issubset(set("MLZ"))


def test_trimmed_arc_to_cubics():
radius = 10
circ = gp_Circ(gp_Ax2(), radius)
trimmed_arc = GC_MakeArcOfCircle(
circ, gp_Pnt(-radius, 0, 0), gp_Pnt(0, +radius, 0), True
).Value()

svg_with_arcs = list(curve_to_svg_path(trimmed_arc, tolerance=1e-6))
svg_with_cubics_only = list(
curve_to_svg_path(
trimmed_arc, use_arcs=False, use_quadratics=False, tolerance=1e-6
)
)
assert svg_with_arcs[0][-2:] == approx(svg_with_cubics_only[0][-2:])
assert svg_with_arcs[-1][-2:] == approx(svg_with_cubics_only[-1][-2:])


def test_trimmed_arc_to_cubics_reversed():
radius = 10
circ = gp_Circ(gp_Ax2(), radius)
trimmed_arc = GC_MakeArcOfCircle(
circ, gp_Pnt(-radius, 0, 0), gp_Pnt(0, +radius, 0), True
).Value()

svg_with_arcs = list(curve_to_svg_path(trimmed_arc, reverse=True, tolerance=1e-6))
svg_with_cubics_only = list(
curve_to_svg_path(
trimmed_arc,
reverse=True,
use_arcs=False,
use_quadratics=False,
tolerance=1e-6,
)
)
assert svg_with_arcs[0][-2:] == approx(svg_with_cubics_only[0][-2:])
assert svg_with_arcs[-1][-2:] == approx(svg_with_cubics_only[-1][-2:])


@pytest.mark.parametrize(
"wire, svg_d, opts",
[
Expand Down
Loading