jamesgregson / pypolycsg Goto Github PK
View Code? Open in Web Editor NEWA Polyhedral CSG library for Python
License: Other
A Polyhedral CSG library for Python
License: Other
I managed to build under cygwin64 (had to change a few argument names in .hpp files). But then when I try to use the code, I get
Python 2.7.12 (default, Oct 10 2016, 12:56:26)
[GCC 5.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyPolyCSG
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initpyPolyCSG)
Any hints? I saw this which suggests it might be a mismatch between the library filename and the boost definitions, but I can't see this being the issue.
OBJ file format lets you set a bunch of vertex properties using various entities which start with v:
# List of Vertices, with (x,y,z[,w]) coordinates, w is optional and defaults to 1.0.
v 0.123 0.234 0.345 1.0
v ...
...
# Texture coordinates, in (u ,v [,w]) coordinates, these will vary between 0 and 1, w is optional and default to 0.
vt 0.500 1 [0]
vt ...
...
# Normals in (x,y,z) form; normals might not be unit.
vn 0.707 0.000 0.707
vn ...
...
# Parameter space vertices in ( u [,v] [,w] ) form; free form geometry statement ( see below )
vp 0.310000 3.210000 2.100000
vp ...
...
https://en.wikipedia.org/wiki/Wavefront_.obj_file#File_format
Your vertex loader only checks that the lines start with V and then load the coordinates in to vertex objects; These entities above should probably be filtered out using no-op's like so:
while( !(getline(input,line)).fail() ){
if ( line[0] == 'v' && line[1] == 'n') {
// No-op; ignore vertex normals
} else if( line[0] == 'v' ){
This lib is very exciting -- I'm in the planning stages of a 2d CAM tool, and have been looking for a CSG package to use to create a visual simulation of the cutting path.
Building on Ubuntu 12.04 LTS required a couple of minor tweaks:
The Carve test geom3d_unittest uses a BSD-ism for initializing the random seed. I put in a Linux equivalent under a simple-minded #if.
Install paths are different, so I tweaked those in setup.py -- I'm not a packaging whiz, so i'm not sure what the best way to fix that really is.
Anyway, the branch ub12.04lts in my fork of your repo has my changes.
I tested compilation on Linux, and my #if doesn't get in they way of that :) But I haven't tested compilation on OS X, so the #if should be treated with suspicion at this point.
-dave
It seems that the mult_matrix_4 function is showing some odd behavior. I defined a 4x4 transformation matrix that should move a shape up by 3 units and then rotate that shape by pi/7 radians about the point (0, 3.5, 0) and about the axis (0,0,1):
tmat = [[ 0.90096887 -0.43388374 0. 0.21694187]
[ 0.43388374 0.90096887 0. 3.04951557]
[ 0. 0. 1. 0. ]
[ 0. 0. 0. 1. ]]
I then flattened the matrix in row-major format, as mult_matrix_4 seems to require:
formatted_tmat = [0.9009688679024191, -0.4338837391175581, 0.0, 0.21694186955877903, 0.4338837391175581, 0.9009688679024191, 0.0, 3.0495155660487905, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
I then made a box in pyPolyCSG and applied the transformation:
a = csg.box(3.0,1.0,1.0)
b = a.mult_matrix_4(formatted_tmat)
In terms of the first 4 vertices (as returned by b.get_vertices()), I get what seems to be a translation + dilation of my shape:
[0.21694187, 3.04951557, 0]
[1.61819726, 3.04951557, 0]
[1.61819726, 4.38436817, 0]
[0.21694187, 4.38436817, 0]
I was expecting to get a translation + rotation of the box, as I do when I multiply the vertex coordinates by the transformation matrix by hand:
[0.216942, 3.04952, 0.]
[2.91985, 4.35117, 0.]
[2.48596, 5.25214, 0]
[-0.216942, 3.95048, 0]
Do you know what's causing the discrepancy, and do you know how I can fix it?
Very interesting project. Is exporting the OBJ the only way to visualize?
If not, is it something you could add? thanks
Simple test case iteratively subtracting a cylinder from a block fails with "unidentifiable C++ exception"
import pyPolyCSG as csg
#probe = 0.9 # works
#probe = 1.0 # works
probe = 1.1 # fails
#probe = 2.0 # fails
block = csg.box(6,2,4,True)
cyl = csg.cylinder(1,4,True)
cyl = cyl.translate(0,probe,0)
offset = 4
i = 0 # keep track of which iteration failed
while offset > -0.4:
print i
i += 1
tool = cyl.translate(offset,0,0)
block -= tool
offset -= 0.5
traceback:
>>> ================================ RESTART ================================
>>>
0
1
2
3
4
Traceback (most recent call last):
File "****/bug01.py", line 18, in <module>
block -= tool
RuntimeError: unidentifiable C++ exception
and in the terminal window running idle:
FACE LOOP ERROR: 0x2918e88-0x2919540 : 2
FACE LOOP ERROR: 0x2918fa0-0x2919338 : 2
FACE LOOP ERROR: 0x2918f00-0x2919108 : 2
FACE LOOP ERROR: 0x29193d8-0x2919568 : 2
FACE LOOP ERROR: 0x2918e60-0x29193b0 : -2
FACE LOOP ERROR: 0x2919108-0x29193b0 : 2
FACE LOOP ERROR: 0x2919518-0x2924a58 : -2
FACE LOOP ERROR: 0x29193d8-0x2919518 : -2
FACE LOOP ERROR: 0x29190e0-0x2924a58 : 2
FACE LOOP ERROR: 0x2918ed8-0x2919568 : -2
FACE LOOP ERROR: 0x2918f78-0x2924a30 : 2
FACE LOOP ERROR: 0x2918e60-0x29190e0 : 2
FACE LOOP ERROR: 0x2918f78-0x2919540 : -2
FACE LOOP ERROR: 0x2918f00-0x29194a0 : -2
FACE LOOP ERROR: 0x29191a8-0x29194a0 : 2
FACE LOOP ERROR: 0x2918ed8-0x2918fa0 : 2
FACE LOOP ERROR: 0x29191a8-0x2924a30 : -2
FACE LOOP ERROR: 0x2918e88-0x2919338 : -2
The "FACE LOOP" message seems to come from:
carve/lib/intersect.cpp
There are 3 open bugs on Carve's issue tracker metioning 'FACE LOOP ERROR', and some Blender issues mentioning 'FACE LOOP ERROR'. These might be coming from an intersect operation leaving behind a degenerate mesh, causing problems for the next intersection operation. Or maybe not. I see Carve defines a Polyhedron::canonicalize() method which you are not yet exporting. I'm speculating that canonicalize() might be worth experimenting with.
Additional info: I speculate that this may be related to the cylinder having a flat bottom -- if I replace the cylinder with a sphere and try the same simulation, I can try many different sizes of sphere and step sizes and it all works fine.
Annnnnnd.... another update.
Changing cylinder creation to:
cyl = csg.cylinder(1,4,True)
cyl = cyl.rotate(0,0,0.1)
cyl = cyl.translate(0,probe,0)
will make the tests pass. So rotation in Z works around what ever bug is showing up here. That kind of blows the flat-bottom theory out of the water.
Is there a way to do collision detection between two csg objects without having to do an intersection and looking for an empty result?
My application for pyPolyCSG is simulation of CNC G-code for milling. The bug reported in issue #6 illustrates the basic idea.
So in my application, collision detection happens at each iteration step along the tool path. It doesn't need full csg, so I suspect the simulation would run a lot faster if it could to collision detection without having to perform csg.
Hello, thank you for the reply about the normals.
Can you please provide a Win32 and / or Win64 binaries, including Carve binaries? (my system is Win64 and my Python is Win32).
I do not understand how to create them...
Hello,
thank you for having added the possibility to get meshes / triangles.
Update: So I recalled that I had never run the Carve library tests in the build directory. Several of those fail for me. So perhaps there is some sort of build problem with Linux. Anyway... will not have time to diagnose it further until next week.
Original post:
The test below repeatedly subtracts a cylinder from a block at varied offsets. Very often, pyPolyCSG throws an 'unidentifiable C++ exception'. But not consistently.
>>> ================================ RESTART ================================
>>>
passed 840
failures:
360 : unidentifiable C++ exception
>>> ================================ RESTART ================================
>>>
passed 841
failures:
359 : unidentifiable C++ exception
>>> ================================ RESTART ================================
>>>
passed 836
failures:
364 : unidentifiable C++ exception
>>> ================================ RESTART ================================
>>>
passed 832
failures:
368 : unidentifiable C++ exception
>>> ================================ RESTART ================================
>>>
passed 837
failures:
363 : unidentifiable C++ exception
The test script is:
# Reliability test for csg subtraction.
# Constructs a block and a cylinder, and repeatedly subtracts
# the cylinder from the box at different locations.
import pyPolyCSG as csg
ctrlDiameter = {'start':0.5, 'end':1.51, 'step':0.25 }
ctrlStep = {'start':0.5, 'end':1.51, 'step':0.25 }
ctrlDepth = {'start':1.5, 'end':3.51, 'step':0.5 }
passes = 0
fails = {}
diameter = ctrlDiameter['start']
while diameter < ctrlDiameter['end']:
# Create a cylinder
# print 'diameter',diameter
cyl = csg.cylinder(diameter,4,True)
depth = ctrlDepth['start']
while depth < ctrlDepth['end']:
# print 'depth',depth
# Set the cylinder depth
cylAtDepth = cyl.translate(0,depth,0)
# Create a box
block = csg.box(6,2,4,True)
step = ctrlStep['start']
while step < ctrlStep['end']:
# print 'step',step
# perform the cutting pass
offset = 4.0
while offset > -4.0:
tool = cylAtDepth.translate(offset,0,0)
try:
block -= tool
status = 'pass'
msg = ''
passes += 1
except Exception as ex:
status = 'fail'
msg = str(ex)
if msg in fails:
fails[msg] += 1
else:
fails[msg] = 1
offset -= step
step += ctrlStep['step']
depth += ctrlDepth['step']
diameter += ctrlDiameter['step']
print 'passed',passes
print 'failures:'
for msg, count in fails.items():
print count, ':', msg
Almost certainly this is coming from Carve. But we need to verify that it is not a bug in pyPolyCSG, then try the development head for Carve to see if the bug is still there, and then probably code up the equivalent test in C++ and file an issue against Carve.
I've noticed that rotating the cylinder slightly will move the failure around.
Since this failure is inconsistent, it could very well be an uninitialized variable in Carve. Perhaps a build of Carve with optimization off is worth a shot -- if the bug goes away with optimization off then that is a good indicator if an uninitialized variable.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.