cadquery
cadquery copied to clipboard
BRep_Tool:: TopoDS_Vertex hasn't gp_Pnt when making a plate from a wire
I am attempting to generate a plate with a given thickness based on a closed wire such as in the example below:
import cadquery as cq
from math import sqrt
import numpy as np
unit_cell_size = 10
thickness = 1
delta_radius = 0.5 - 0.5/sqrt(2)
edge_points = [
[[0.0, 0.5],
[delta_radius, delta_radius],
[0.5, 0.0]],
[[0.0, 0.5],
[delta_radius, delta_radius],
[0.5, 0.0]],
[[0.0, 0.5],
[delta_radius, delta_radius],
[0.5, 0.0]],
[[-0.5, 0.0],
[-delta_radius,-delta_radius],
[0.0, -0.5]],
[[-0.5, 0.0],
[-delta_radius,-delta_radius],
[0.0, -0.5]],
[[-0.5, 0.0],
[-delta_radius,-delta_radius],
[0.0, -0.5]]
]
edge_points = np.array(edge_points) * unit_cell_size
plane_list = ["XZ", "XY", "YZ", "XZ", "YZ", "XY"]
offset_list = [- 1, 1, 1, 1, - 1, - 1]
offset_list = np.array(offset_list) * unit_cell_size * 0.5
edge_wire = (
cq.Workplane(plane_list[0])
.workplane(offset = - offset_list[0])
.spline(edge_points[0])
)
for i in range(len(edge_points) - 1):
edge_wire = edge_wire.add(
cq.Workplane(plane_list[i + 1])
.workplane(offset = - offset_list[i + 1])
.spline(edge_points[i + 1])
)
surface_points = [[0, 0, 0]]
plate = cq.Workplane("XY")
plate = plate.interpPlate(edge_wire, surface_points, thickness)
However, I see the following error when I try to make an interpPlate
:
plate = plate.interpPlate(edge_wire, surface_points, thickness)
------------------------
Standard_NullObjectTraceback (most recent call last)
<ipython-input-4-03580d26568b> in <module>
63 surface_points = [[0, 0, 0]]
64 plate = cq.Workplane("XY")
---> 65 plate = plate.interpPlate(edge_wire, surface_points, thickness)
~/anaconda3/envs/cqgui/lib/python3.8/site-packages/cadquery/cq.py in interpPlate(self, surf_edges, surf_pts, thickness, combine, clean, degree, nbPtsOnCur, nbIter, anisotropy, tol2d, tol3d, tolAng, tolCurv, maxDeg, maxSegments)
3314
3315 # Creates interpolated plate
-> 3316 p = Solid.interpPlate(
3317 surf_edges,
3318 surf_pts,
~/anaconda3/envs/cqgui/lib/python3.8/site-packages/cadquery/occ_impl/shapes.py in interpPlate(cls, surf_edges, surf_pts, thickness, degree, nbPtsOnCur, nbIter, anisotropy, tol2d, tol3d, tolAng, tolCurv, maxDeg, maxSegments)
2158 True,
2159 ) # The last True is important to make solid
-> 2160 solid.MakeOffsetShape()
2161 return cls(solid.Shape())
2162 else: # Return 2D surface only
Standard_NullObject: BRep_Tool:: TopoDS_Vertex hasn't gp_Pnt
The edge_wire
itself is generated with no problems and looks like this:
This is looks strange for me because the same code works perfectly for another set of points:
edge_points = [
[[0.5, 0.5],
[0.25, 0.0],
[0.5, - 0.5]],
[[- 0.5, - 0.5],
[0.0, - 0.25],
[0.5, - 0.5]],
[[- 0.5, - 0.5],
[0.0, - 0.25],
[0.5, - 0.5]],
[[- 0.5, - 0.5],
[- 0.25, 0.0],
[- 0.5, 0.5]],
[[0.5, 0.5],
[0.0, 0.25],
[- 0.5, 0.5]],
[[0.5, 0.5],
[0.0, 0.25],
[- 0.5, 0.5]],
]
and the result in this case is very nice.
Perhaps I am missing something?
I managed find a workaround for it by using arcs instead of splines for the wire:
delta_radius = 0.5 - 0.5/sqrt(2)
convex_pnts = [[0.0, 0.5],
[delta_radius, delta_radius],
[0.5, 0.0]]
nonconvex_pnts = [[-0.5, 0.0],
[-delta_radius,-delta_radius],
[0.0, -0.5]]
edge_points = [convex_pnts,
nonconvex_pnts,
convex_pnts,
nonconvex_pnts,
convex_pnts,
nonconvex_pnts]
edge_points = np.array(edge_points) * unit_cell_size
plane_list = ["XZ", "XY", "YZ", "XZ", "XY", "YZ"]
offset_list = [- 1, - 1, 1, 1, 1, - 1]
offset_list = np.array(offset_list) * unit_cell_size * 0.5
edge_wire = (
cq.Workplane(plane_list[0])
.workplane(offset = - offset_list[0])
.moveTo(edge_points[0][0][0],
edge_points[0][0][1])
.threePointArc(tuple(edge_points[0][1]),
tuple(edge_points[0][2]))
)
for i in range(len(edge_points) - 1):
edge_wire = edge_wire.add(
cq.Workplane(plane_list[i + 1])
.workplane(offset = - offset_list[i + 1])
.moveTo(edge_points[i + 1][0][0],
edge_points[i + 1][0][1])
.threePointArc(tuple(edge_points[i + 1][1]),
tuple(edge_points[i + 1][2]))
)
surface_points = [[0, 0, 0]]
plate_4 = cq.Workplane("XY")
plate_4 = plate_4.interpPlate(edge_wire, surface_points, thickness)
But I still wonder why there are issues with splines? I wonder if OpenCascade having troubles connecting the splines or I do something wrong?
I wonder if OpenCascade having troubles connecting the splines
It could be that with splines the wire was not being closed properly for some reason.
Looks like the issue occur in the offset generation part. Do you get a correct surface without the offset?
The following might be a solution, at least it worked for me.
In shapes.py
, I modified the assembleEdges()
method by replacing:
for e in listOfEdges:
wire_builder.Add(e.wrapped)
with
occ_edges_list = TopTools_ListOfShape()
for e in listOfEdges:
occ_edges_list.Append(e.wrapped)
wire_builder.Add(occ_edges_list)
my two cents is that it might take advantage of the following property :
The edges are not to be consecutive
(https://dev.opencascade.org/doc/refman/html/class_b_rep_builder_a_p_i___make_wire.html#ae9dd6e34dfd1bc0df8dc3b9c01bb97c2)
void BRepBuilderAPI_MakeWire::Add (const TopTools_ListOfShape & L)
Adds the edges of <L> to the current wire. The edges are not to be consecutive.
But they are to be all connected geometrically or topologically.
If some of them are not connected the Status give DisconnectedWire
but the "Maker" is Done() and you can get the partial result.
(ie connected to the first edgeof the list <L>)
This is working in current master with change to surface_points as follows:
surface_points = [[0, 0, 0]]
->
surface_points = [(0, 0, 0)]
Thanks for checking @lorenzncode !