diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..47e0b6d --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,11 @@ +include Makefile +include setup_build.py +include setup_docs.py +include version.py +include MANIFEST.in +include README.rst +include TODO.rst +include LICENSE.txt +recursive-include occmodel *.py *.pyx *.pxi *.pxd *.rst *.cpp *.h +exclude occmodel/test.py occmodel/test2.py occmodel/Note.rst +prune occmodel/@arch \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8d61470 --- /dev/null +++ b/Makefile @@ -0,0 +1,65 @@ +# +# File: Makefile (for library) +# +# The variables 'PYTHON' and 'PYVER' can be modified by +# passing parameters to make: make PYTHON=python PYVER=2.6 +# +PYTHON=python2 +PYVER=2.7 + +CC=g++ +CFLAGS=-Wall -fPIC -O2 -frtti -fexceptions -Isrc -I/usr/include/oce +LIB=occmodel/liboccmodel.a + +LIBSRC = $(wildcard occmodel/@src/*.cpp) + +LIBOBJ=$(LIBSRC:.cpp=.o) + +.PHONY: pylib docs test tests install clean + +$(LIB): $(LIBOBJ) + @echo lib Makefile - archiving $(LIB) + @$(AR) r $(LIB) $(LIBOBJ) + +.cpp.o: + @echo lib Makefile - compiling $< + @$(CC) $(CFLAGS) -c $< -o $@ + +pylib: $(LIB) + @echo lib Makefile - building python extension + $(PYTHON) setup_build.py build_ext --inplace + +docs: pylib + @echo lib Makefile - building documentation + @cd occmodel/@docs ; $(PYTHON) ../../setup_docs.py build_sphinx + @cp -rf occmodel/@docs/build/sphinx/html/* occmodel/@docs/html/ + +test: pylib + @echo lib Makefile - running test file + $(PYTHON) occmodel/test.py + +tests: pylib + @echo lib Makefile - running test suite + @cd occmodel/@tests ; $(PYTHON) runAll.py + +install: pylib + @cp occmodel.so ~/.local/lib/python$(PYVER)/site-packages/ + @cp occmodelviewer.so ~/.local/lib/python$(PYVER)/site-packages/ + +sdist: clean + @echo lib Makefile - creating source distribution + $(PYTHON) setup_build.py sdist --formats=gztar,zip + +clean: + -rm $(LIBOBJ) + -rm $(LIB) + -rm -rf build dist + -rm -rf occmodel/@docs/build + -rm -rf occmodel/@docs/html + -rm MANIFEST occmodel/@src/Config.pxi + -rm occmodel.so occmodel/occmodel.cpp + -rm occmodelviewer.so occmodel/occmodelviewer.c + -find occmodel -iname '*.so' -exec rm {} \; + -find occmodel -iname '*.pyc' -exec rm {} \; + -find occmodel -iname '*.pyo' -exec rm {} \; + -find occmodel -iname '*.pyd' -exec rm {} \; \ No newline at end of file diff --git a/README.rst b/README.rst index 2ac3ee3..d11d940 100644 --- a/README.rst +++ b/README.rst @@ -20,12 +20,25 @@ The license is GPL v2. Building ======== - * Python 2.7 and Cython 0.17. + * Python 2.7/3.x and Cython 0.17 or later. * A working installation of OpenCASCADE (OCE prefered) * The geotools_ library. * The optional viewer and demo needs the gltools_ library. -The extension have only been build on the Linux platform. +Note that currently I can not find a way to install the required +Cython 'pxd' files with distutils and this file has to be copied +manually. + +On the Windows platform installers are available on the +pypi_ web site. It is possible to build the module from source +with the help of the express edition of Visual Studio, but the +process is rather involved compared to Linux. + +To complete the windows installation the OpenCASCADE dll's must be +installed and placed in the system path. Prebuilt binaries are available +on the OCE_ project site. The python 2.7 module is linked against +'OCE-0.10.0-Win-MSVC2008.zip' and the python 3.3 module is +linked against 'OCE-0.10.0-Win-MSVC2010.zip'. Documentation ============= @@ -36,4 +49,8 @@ See online Sphinx docs_ .. _geotools: http://github.com/tenko/geotools -.. _gltools: https://github.com/tenko/gltools \ No newline at end of file +.. _gltools: https://github.com/tenko/gltools + +.. _pypi: http://pypi.python.org/pypi/occmodel + +.. _OCE: https://github.com/tpaviot/oce/downloads \ No newline at end of file diff --git a/TODO.rst b/TODO.rst index 847ce43..0fba277 100644 --- a/TODO.rst +++ b/TODO.rst @@ -1,4 +1,4 @@ ToDo ---- - * Migrate building to CMake or similiar + * Optimize viewer diff --git a/occmodel/@src/OCCModel.cpp b/occmodel/@src/OCCModel.cpp index 213aab5..bbc11ad 100644 --- a/occmodel/@src/OCCModel.cpp +++ b/occmodel/@src/OCCModel.cpp @@ -102,7 +102,7 @@ int OCCMesh::extractFaceMesh(const TopoDS_Face& face, bool qualityNormals = fals pt.Get(n1,n2,n3); // make sure that we don't process invalid triangle - if (n1 == n2 or n2 == n3 or n3 == n1) + if (n1 == n2 || n2 == n3 || n3 == n1) continue; // Calculate face normal diff --git a/occmodel/Makefile b/occmodel/Makefile deleted file mode 100644 index daf6711..0000000 --- a/occmodel/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# File: Makefile (for library) -# -PYTHON=python2 -CC=g++ -CFLAGS=-Wall -fPIC -O2 -frtti -fexceptions -Isrc -I/usr/include/oce -LIB=liboccmodel.a - -LIBSRC = $(wildcard @src/*.cpp) - -LIBOBJ=$(LIBSRC:.cpp=.o) - -.PHONY: pylib docs test tests install clean - -$(LIB): $(LIBOBJ) - @echo lib Makefile - archiving $(LIB) - @$(AR) r $(LIB) $(LIBOBJ) - -.cpp.o: - @echo lib Makefile - compiling $< - @$(CC) $(CFLAGS) -c $< -o $@ - -pylib: $(LIB) - @echo lib Makefile - building python extension - $(PYTHON) setup_build.py build_ext --inplace - -docs: pylib - @echo lib Makefile - building documentation - @cd @docs ; $(PYTHON) ../setup_docs.py build_sphinx - @cp -rf @docs/build/sphinx/html/* @docs/html/ - -test: pylib - @echo lib Makefile - running test file - $(PYTHON) test.py - -tests: pylib - @echo lib Makefile - running test suite - @cd @tests ; $(PYTHON) runAll.py - -install: pylib - @cp occmodel.so ~/.local/lib/python2.7/site-packages/ - -clean: - -rm $(LIBOBJ) - -rm $(LIB) - -rm -rf build - -rm occmodel.so - -rm occmodel.cpp \ No newline at end of file diff --git a/occmodel/occmodel.pyx b/occmodel/occmodel.pyx index 50feae2..41f55ab 100644 --- a/occmodel/occmodel.pyx +++ b/occmodel/occmodel.pyx @@ -3,6 +3,7 @@ # Copyright 2012 by Runar Tenfjord, Tenko as. # See LICENSE.txt for details on conditions. include "OCCIncludes.pxi" +include "Config.pxi" class OCCError(Exception): pass diff --git a/occmodel/occmodeldemo.py b/occmodel/occmodeldemo.py index dccbea0..67776e4 100644 --- a/occmodel/occmodeldemo.py +++ b/occmodel/occmodeldemo.py @@ -1,4 +1,6 @@ +#!/usr/bin/python2 # -*- coding: utf-8 -*- +import sys import math import geotools as geo @@ -18,7 +20,11 @@ class Demo: 'Solid':occ.Solid, 'SWEEP_RIGHT_CORNER': occ.SWEEP_RIGHT_CORNER, } - exec(self.TEXT) in loc + if sys.hexversion > 0x03000000: + exec(self.TEXT, loc) + else: + exec(self.TEXT) in loc + return self.results(loc) class Edge_1(Demo): diff --git a/occmodel/occmodelviewer.py b/occmodel/occmodelviewer.pyx similarity index 99% rename from occmodel/occmodelviewer.py rename to occmodel/occmodelviewer.pyx index 382b40f..5c5bb03 100644 --- a/occmodel/occmodelviewer.py +++ b/occmodel/occmodelviewer.pyx @@ -7,10 +7,18 @@ import itertools import ctypes import atexit +cimport geotools as geo import geotools as geo + +cimport gltools as gl import gltools as gl + import occmodel as occ - +from occmodel import OCCError + +if sys.hexversion > 0x03000000: + basestring = str + class InputHookManager(object): """ Manage PyOS_InputHook. @@ -89,7 +97,7 @@ COLORS = { 'blue' :gl.ColorRGBA(0,0,255,255), 'yellow':gl.ColorRGBA(255,255,0,255), 'white' :gl.ColorRGBA(0,0,0,0), - 'grey' :gl.ColorRGBA(128,128,128,255), + 'grey' :gl.ColorRGBA(128,128,128,255), 'black' :gl.ColorRGBA(255,255,255,255), } @@ -216,7 +224,7 @@ class Viewer(gl.Window): if color.lower() in COLORS: color = COLORS[color.lower()] else: - raise GLError("Unknown color: '%s'" % color) + raise OCCError("Unknown color: '%s'" % color) if isinstance(obj, (occ.Edge, occ.Wire)): res = PolylineObj(obj.hashCode()) @@ -335,7 +343,7 @@ class Viewer(gl.Window): self.objects.add(obj) else: - raise GLError('unknown object type') + raise OCCError('unknown object type') return True @@ -619,7 +627,7 @@ class Viewer(gl.Window): # set color from counter color.fromInt(cnt) if color.alpha != 0: - raise GLError('to many object to pick') + raise OCCError('to many object to pick') color.alpha = 255 gl.Color(color) diff --git a/occmodel/setup_build.py b/occmodel/setup_build.py deleted file mode 100644 index cf5ad7a..0000000 --- a/occmodel/setup_build.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/python2 -# -*- coding: utf-8 -*- -# -# This file is part of occmodel - See LICENSE.txt -# -import sys -import os -import glob -import shutil - -from distutils.core import setup -from distutils.extension import Extension -from Cython.Distutils import build_ext - -CPPFLAGS = ["-fpermissive"] -OCCINCLUDE = '/usr/include/oce' - -OCCLIBS = [ - 'FWOSPlugin', - 'PTKernel', - 'TKAdvTools', - 'TKBO', - 'TKBRep', - 'TKBin', - 'TKBinL', - 'TKBinTObj', - 'TKBinXCAF', - 'TKBool', - 'TKCAF', - 'TKCDF', - 'TKFeat', - 'TKFillet', - 'TKG2d', - 'TKG3d', - 'TKGeomAlgo', - 'TKGeomBase', - 'TKHLR', - 'TKIGES', - 'TKLCAF', - 'TKMath', - 'TKMesh', - 'TKOffset', - 'TKPCAF', - 'TKPLCAF', - 'TKPShape', - 'TKPrim', - 'TKSTEP', - 'TKSTEP209', - 'TKSTEPAttr', - 'TKSTEPBase', - 'TKSTL', - 'TKService', - 'TKShHealing', - 'TKShapeSchema', - 'TKStdLSchema', - 'TKStdSchema', - 'TKTObj', - 'TKTopAlgo', - 'TKV2d', - 'TKV3d', - 'TKVRML', - 'TKXCAF', - 'TKXCAFSchema', - 'TKXDEIGES', - 'TKXDESTEP', - 'TKXMesh', - 'TKXSBase', - 'TKXml', - 'TKXmlL', - 'TKXmlTObj', - 'TKXmlXCAF', - 'TKernel', -] - -try: - setup( - name = 'occmodel', - ext_modules=[ - Extension("occmodel", - sources=["occmodel.pyx"], - depends = ["liboccmodel.a",] + glob.glob("@src/*.pxd") + \ - glob.glob("@src/*.pxi"), - include_dirs = ['@src', OCCINCLUDE], - library_dirs = ['.'], - libraries = ["occmodel", "pthread"] + OCCLIBS, - extra_compile_args = CPPFLAGS, - language="c++"), - ], - - cmdclass = {'build_ext': build_ext} - ) -except: - print('Traceback\n:%s\n' % str(sys.exc_info()[-2])) - sys.exit(1) -else: - print('\n') \ No newline at end of file diff --git a/setup_build.py b/setup_build.py new file mode 100644 index 0000000..83b7939 --- /dev/null +++ b/setup_build.py @@ -0,0 +1,133 @@ +#!/usr/bin/python2 +# -*- coding: utf-8 -*- +# +# This file is part of occmodel - See LICENSE.txt +# +import sys +import os +import glob +import shutil + +from distutils.core import setup +from distutils.extension import Extension + +try: + from Cython.Distutils import build_ext +except ImportError: + print >>sys.stderr, "Cython is required to build occmodel" + sys.exit(1) + +try: + import geotools +except ImportError: + print >>sys.stderr, "geotools is required to build occmodel" + sys.exit(1) + +viewer = True +try: + import gltools +except ImportError: + viewer = False + +#sys.argv.append('build_ext') +#sys.argv.extend(['sdist','--formats=gztar,zip']) +#sys.argv.append('bdist_wininst') + +# create config file +sys.dont_write_bytecode = True +import version + +CONFIG = 'occmodel/@src/Config.pxi' +if not os.path.exists(CONFIG) and 'sdist' not in sys.argv: + with open(CONFIG, 'w') as fh: + fh.write("__version__ = '%s'\n" % version.STRING) + args = version.MAJOR, version.MINOR, version.BUILD + fh.write("__version_info__ = (%d,%d,%d)\n" % args) + +OCC = \ +'''FWOSPlugin PTKernel TKAdvTools TKBO TKBRep TKBin TKBinL TKBinTObj TKBinXCAF TKBool +TKCAF TKCDF TKFeat TKFillet TKG2d TKG3d TKGeomAlgo TKGeomBase TKHLR TKIGES TKLCAF +TKMath TKMesh TKOffset TKPCAF TKPLCAF TKPShape TKPrim TKSTEP TKSTEP209 TKSTEPAttr +TKSTEPBase TKSTL TKService TKShHealing TKShapeSchema TKStdLSchema TKStdSchema +TKTObj TKTopAlgo TKV2d TKV3d TKVRML TKXCAF TKXCAFSchema TKXDEIGES TKXDESTEP +TKXMesh TKXSBase TKXml TKXmlL TKXmlTObj TKXmlXCAF TKernel''' + +# platform specific settings +OBJECTS, LIBS, LINK_ARGS, COMPILE_ARGS = [],[],[],[] +if sys.platform == 'win32': + COMPILE_ARGS.append('/EHsc') + OCCINCLUDE = r"C:\vs9include\oce" + OCCLIBS = [] + OBJECTS = [name + '.lib' for name in OCC.split()] + ['occmodel.lib',] +else: + OCCINCLUDE = '/usr/include/oce' + OCCLIBS = OCC.split() + LIBS.append("occmodel") + LIBS.append("pthread") + COMPILE_ARGS.append("-fpermissive") + +EXTENSIONS = [ + Extension("occmodel", + sources = ["occmodel/occmodel.pyx"], + depends = glob.glob("occmodel/@src/*.pxd") + \ + glob.glob("occmodel/@src/*.pxi"), + include_dirs = ['occmodel/@src', OCCINCLUDE], + library_dirs = ['occmodel'], + libraries = LIBS + OCCLIBS, + extra_link_args = LINK_ARGS, + extra_compile_args = COMPILE_ARGS, + extra_objects = OBJECTS, + language="c++" + ) +] + +# only build viewer of gltools is available +if viewer: + EXTENSIONS.append( + Extension("occmodelviewer", sources = ["occmodel/occmodelviewer.pyx"]), + ) + +classifiers = '''\ +Development Status :: 4 - Beta +Environment :: MacOS X +Environment :: Win32 (MS Windows) +Environment :: X11 Applications +Intended Audience :: Science/Research +License :: OSI Approved :: GNU General Public License v2 (GPLv2) +Operating System :: OS Independent +Programming Language :: Cython +Topic :: Scientific/Engineering +''' + +try: + setup( + name = 'occmodel', + version = version.STRING, + description = 'Easy access to the OpenCASCADE library', + long_description = \ +'''**occmodel** is a small library which gives a high level access +to the OpenCASCADE modelling kernel. + +For most users a direct use of the OpenCASCADE modelling +kernel can be quite a hurdle as it is a huge library. + +The geometry can be visualized with the included viewer. +This viewer is utilizing modern OpenGL methods like GLSL +shaders and vertex buffers to ensure visual quality and +maximum speed. To use the viewer OpenGL version 2.1 is +needed. +''', + classifiers = [value for value in classifiers.split("\n") if value], + author='Runar Tenfjord', + author_email = 'runar.tenfjord@gmail.com', + license = 'GPLv2', + download_url='http://pypi.python.org/pypi/occmodel/', + url = 'http://github.com/tenko/occmodel', + platforms = ['any'], + scripts = ['occmodel/occmodeldemo.py'], + ext_modules = EXTENSIONS, + cmdclass = {'build_ext': build_ext} + ) +except: + print('Traceback\n:%s\n' % str(sys.exc_info()[-2])) + sys.exit(1) \ No newline at end of file diff --git a/occmodel/setup_docs.py b/setup_docs.py similarity index 72% rename from occmodel/setup_docs.py rename to setup_docs.py index d49441a..47bbaf7 100644 --- a/occmodel/setup_docs.py +++ b/setup_docs.py @@ -16,19 +16,17 @@ release = '0.1.0' try: setup( - name=name, - author='Runar Tenfjord', - version=release, - cmdclass=cmdclass, - command_options={ + name = name, + author = 'Runar Tenfjord', + version = release, + cmdclass = cmdclass, + command_options = { 'build_sphinx': { 'builder': ('setup_docs.py', 'html'), - } + } }, ) except: print('Traceback\n:%s\n' % str(sys.exc_info()[-2])) - sys.exit(1) -else: - print('\n') \ No newline at end of file + sys.exit(1) \ No newline at end of file diff --git a/version.py b/version.py new file mode 100644 index 0000000..22f3f6c --- /dev/null +++ b/version.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +MAJOR = 0 +MINOR = 1 +BUILD = 0 +STRING = "%d.%d.%d" % (MAJOR,MINOR,BUILD) \ No newline at end of file