BinTools.Read_s not working with BytesIO stream
bernhard-42 opened this issue · 5 comments
I'd like to serialize OCP objects and found that BinTools is faster than BRepTools. Do I'd like to give BinTools
a try.
Storing as a file works:
obj = cq.Workplane().box(1,2,1).val().wrapped
rv = BinTools.Write_s(obj, "obj.bin")
shape = TopoDS_Shape()
BinTools.Read_s(shape, "obj.bin")
However, using BytesIO
stream doesn't:
obj = cq.Workplane().box(1,2,1).val().wrapped
bio = io.BytesIO()
rv = BinTools.Write_s(obj, bio)
buffer = bio.getvalue()
bio2 = io.BytesIO(buffer)
BinTools.Read_s(shape, bio2)
fails with
---------------------------------------------------------------------------
Standard_Failure Traceback (most recent call last)
Input In [47], in <module>
5 buffer = bio.getvalue()
7 bio2 = io.BytesIO(buffer)
----> 8 BinTools.Read_s(shape, bio2)
Standard_Failure: EXCEPTION in BinTools_Curve2dSet::ReadCurve2d(...)
0x560930b56d30 : Standard_ConstructionError: gp_Dir2d::SetCoord() - result vector has zero norm
What am I doing wrong?
Btw., it works with an BRepTools
and BytesIO
stream:
obj = cq.Workplane().box(2,2,1).val().wrapped
bio = io.BytesIO()
rv = BRepTools.Write_s(obj, bio)
buffer = bio.getvalue()
bio2 = io.BytesIO(buffer)
builder = BRep_Builder()
BRepTools.Read_s(shape, bio2, builder)
I compared the file written by the file version or BinTools.Write_s and the buffer, and it turns out that the BytesIO buffer seems to have omitted the bytes 1024, 2048, 3072, ...
Could it be that the BytesIO stream works with a 1024 byte buffer and something is going wrong with reading the chunks?
I don't know if this will fix your problem, but in my apps I successfully use BinTool_ShapeSet
(not the BinTools
static methods).
This isn't a complete example, but you should get the gist of it.
def to_bytes(shape) -> bytes:
s = BinTools.BinTools_ShapeSet()
s.Add(shape)
s.SetWithTriangles(False) # don't serialize triangulations
b = io.BytesIO()
s.Write(b)
return b.getvalue()
def from_bytes(b: bytes):
s = BinTools.BinTools_ShapeSet()
stream = io.BytesIO(b)
s.Read(stream)
shape = s.Shape(s.NbShapes())
return shape
Thanks @whophil
Trying
obj = cq.Workplane().box(1,2,1).val().wrapped
x = to_bytes(obj)
s = from_bytes(bytes(x))
I get
---------------------------------------------------------------------------
Standard_Failure Traceback (most recent call last)
Input In [159], in <module>
1 obj = cq.Workplane().box(1,2,1).val().wrapped
3 x = to_bytes(obj)
----> 4 s = from_bytes(bytes(x))
Input In [154], in from_bytes(b)
10 s = BinTools_ShapeSet()
11 stream = io.BytesIO(b)
---> 12 s.Read(stream)
13 shape = s.Shape(s.NbShapes())
14 return shape
Standard_Failure: EXCEPTION in BinTools_Curve2dSet::ReadCurve2d(...)
0x560930b56d30 : Standard_ConstructionError: gp_Dir2d::SetCoord() - result vector has zero norm
I just checked, I use OCP 7.5.2
@whophil I quickly created a new environment with cadquery=master and OCP=7.5.3
In this environment your code works. So it's a bug in 7.5.2
Upgraded my environment to the latest master (including OCP 7.5.3).
Now all works, @whophil 's code and mine above.
Thanks