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

BRep_Tool:: TopoDS_Vertex hasn't gp_Pnt when making a plate from a wire #890

Closed
jalovisko opened this issue Sep 23, 2021 · 6 comments
Closed

Comments

@jalovisko
Copy link

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:
2021-09-22_22-18

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.
2021-09-22_22-23

Perhaps I am missing something?

@jalovisko
Copy link
Author

jalovisko commented Sep 23, 2021

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)

2021-09-23_15-48
But I still wonder why there are issues with splines? I wonder if OpenCascade having troubles connecting the splines or I do something wrong?

@jmwright
Copy link
Member

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.

@adam-urbanczyk
Copy link
Member

Looks like the issue occur in the offset generation part. Do you get a correct surface without the offset?

@bragostin
Copy link
Contributor

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>)

@lorenzncode
Copy link
Member

This is working in current master with change to surface_points as follows:
surface_points = [[0, 0, 0]]
->
surface_points = [(0, 0, 0)]

@adam-urbanczyk
Copy link
Member

Thanks for checking @lorenzncode !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants