Skip to content

Commit

Permalink
fix bezier approximation
Browse files Browse the repository at this point in the history
  • Loading branch information
snoyer committed Jan 11, 2025
1 parent 0a2a8e3 commit 5d6e8c0
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
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

0 comments on commit 5d6e8c0

Please sign in to comment.