1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
# Copyright (c) 2021-2022, Manfred Moitzi
# License: MIT License
import pathlib
import ezdxf
from ezdxf import zoom
from ezdxf.math import ConstructionArc, BSpline
CWD = pathlib.Path("~/Desktop/Outbox").expanduser()
if not CWD.exists():
CWD = pathlib.Path(".")
# ------------------------------------------------------------------------------
# This is a more theoretical example which shows how to recreate an ARC entity
# from a SPLINE entity, assuming the SPLINE represents an ARC.
# ------------------------------------------------------------------------------
doc = ezdxf.new()
msp = doc.modelspace()
# create the source ARC:
arc = msp.add_arc(
(0, 0),
radius=5,
start_angle=15,
end_angle=165,
dxfattribs={
"layer": "source arc",
"color": ezdxf.const.RED,
},
)
# create a SPLINE entity from ARC, in your scenario these are the source
# entities of your DXF document!
spline = msp.add_spline(
dxfattribs={
"layer": "B-Spline",
"color": ezdxf.const.YELLOW,
}
)
# create a B-spline construction tool from ARC
arc_tool = arc.construction_tool()
bspline = BSpline.from_arc(arc_tool)
spline.apply_construction_tool(bspline)
# ------------------------------------------------------------------------------
# Recreate ARC from SPLINE, if you ASSUME or KNOW it represents an ARC:
# for spline in msp.query("SPLINE):
# ...
# ------------------------------------------------------------------------------
# 1. get the B-spline construction tool from the SPLINE entity
bspline = spline.construction_tool()
max_t = bspline.max_t
# calculate 3 significant points and 2 check points of the SPLINE:
start, chk1, middle, chk2, end = bspline.points(
[0, max_t * 0.25, max_t * 0.5, max_t * 0.75, max_t]
)
# create an arc from 3 points:
arc_tool = ConstructionArc.from_3p(start, end, middle)
arc_tool.add_to_layout(
msp,
dxfattribs={
"layer": "recreated arc",
"color": ezdxf.const.MAGENTA,
},
)
# This only works for flat B-splines in the xy-plane, a.k.a. 2D splines!
# Verify the assumption:
center = arc_tool.center
radius = arc_tool.radius
err = max(abs(radius - p.distance(center)) for p in (chk1, chk2))
print(f"max error: {err:.6f}")
# Warning: this does not proof that the assumption was correct, it's always
# possible to create a diverging B-spline which matches the check points:
foul = (4.5, 1)
fit_points = [start, foul, chk1, middle, chk2, end]
msp.add_spline(
fit_points,
dxfattribs={
"layer": "foul B-spline",
"color": ezdxf.const.RED,
},
)
# add checkmarks
for p in fit_points:
msp.add_circle(p, radius=0.03, dxfattribs={"color": ezdxf.const.RED})
zoom.objects(msp, [arc])
doc.saveas(CWD / "arc_recreation.dxf")
|