diff --git a/Makefile b/Makefile index 8cfb98c..211cadc 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ .PHONY: dist docs dist: + # make dist version="X.X.X" rm -rf dist mkdir dist make dist_source - make dist_docs + make dist_docs version=$(version) make dist_examples clean_examples: @@ -31,14 +32,13 @@ clean: rm -f ./*.sta rm -f ./*.out - dist_examples: make clean_examples zip -r examples.zip examples mv examples.zip dist/ -docs: - # make docs version="0.9.5" +dist_docs: + # make dist_docs version="X.X.X" rm -rf docs rm -rf documentation sphinx-apidoc -F -H "pycalculix" -V $(version) -A "Justin Black" -o docs pycalculix diff --git a/README.md b/README.md index 66ac679..53739d5 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,13 @@ Initial Release: December 2014 ## Change Log +#### 1.1.2 +- Sets part.left/right/top/bottom using geometry.ACC constant, tests added +- Fixes issue https://github.com/spacether/pycalculix/issues/57 where part.left + was not being set if a line was slightly skewed +- Fixes a mac install issue where gcc@7 was assuming a specific X.X.X version + of gcc7 + #### 1.1.1 - Omits test_pinned_plate from Mac OS X with Python >= 3.6 because it does not converge in ccx diff --git a/dist/documentation.zip b/dist/documentation.zip index e39bd84..3e4250d 100644 Binary files a/dist/documentation.zip and b/dist/documentation.zip differ diff --git a/dist/examples.zip b/dist/examples.zip index 09b7dd1..b5649bf 100644 Binary files a/dist/examples.zip and b/dist/examples.zip differ diff --git a/dist/pycalculix-0.9.6.zip b/dist/pycalculix-1.1.2.zip similarity index 54% rename from dist/pycalculix-0.9.6.zip rename to dist/pycalculix-1.1.2.zip index a0b2f26..9150a80 100644 Binary files a/dist/pycalculix-0.9.6.zip and b/dist/pycalculix-1.1.2.zip differ diff --git a/docs/Makefile b/docs/Makefile index b201142..298ea9e 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,6 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build -SPHINXPROJ = pycalculix SOURCEDIR = . BUILDDIR = _build diff --git a/docs/conf.py b/docs/conf.py index bf8bbee..edba93a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,7 +14,7 @@ # # import os # import sys -# sys.path.insert(0, '/Users/justin/Documents/programming/pycalculix/pycalculix') +# sys.path.insert(0, '/Users/justin/programming/pycalculix/pycalculix') # -- Project information ----------------------------------------------------- @@ -24,9 +24,9 @@ author = 'Justin Black' # The short X.Y version -version = '' +version = '1.1.2' # The full version, including alpha/beta/rc tags -release = '' +release = '1.1.2' # -- General configuration --------------------------------------------------- @@ -65,11 +65,11 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path . +# This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = None # -- Options for HTML output ------------------------------------------------- @@ -162,9 +162,6 @@ # Bibliographic Dublin Core info. epub_title = project -epub_author = author -epub_publisher = author -epub_copyright = copyright # The unique identifier of the text. This can be a ISBN number # or the project homepage. @@ -184,10 +181,7 @@ # -- Options for todo extension ---------------------------------------------- # If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True -from pycalculix.version import __version__ -version = __version__ -release = version +todo_include_todos = True extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.todo', diff --git a/docs/index.rst b/docs/index.rst index f93d6d8..884a439 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,5 +1,5 @@ .. pycalculix documentation master file, created by - sphinx-quickstart on Wed Jun 27 21:15:32 2018. + sphinx-quickstart on Sun Dec 23 14:21:14 2018. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. diff --git a/docs/make.bat b/docs/make.bat index b37d90c..27f573b 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -9,7 +9,6 @@ if "%SPHINXBUILD%" == "" ( ) set SOURCEDIR=. set BUILDDIR=_build -set SPHINXPROJ=pycalculix if "%1" == "" goto help diff --git a/pycalculix/cadimporter.py b/pycalculix/cadimporter.py index b5cb60b..bb5f993 100644 --- a/pycalculix/cadimporter.py +++ b/pycalculix/cadimporter.py @@ -3,7 +3,6 @@ import collections import math import os -import pdb # needed to prevent dxfgrabber from crashing on import os.environ['DXFGRABBER_CYTHON'] = 'OFF' import dxfgrabber # needed for dxf files @@ -213,7 +212,6 @@ def __load_dxf(self): Returns: list: list of Part """ - # pdb.set_trace() print('Loading file: %s' % self.__fname) dwg = dxfgrabber.readfile(self.__fname) lines = [item for item in dwg.entities if item.dxftype == 'LINE'] @@ -238,7 +236,6 @@ def __load_dxf(self): # remove all lines that are not part of areas dangling_points = self.__dangling_points(all_points) - # pdb.set_trace() pruned_geometry = bool(dangling_points) while dangling_points: for point in dangling_points: diff --git a/pycalculix/installer.py b/pycalculix/installer.py index 2a8f4c5..3be3f4d 100644 --- a/pycalculix/installer.py +++ b/pycalculix/installer.py @@ -1,7 +1,6 @@ import glob import os -import pdb import re import shutil import shlex @@ -132,24 +131,29 @@ def mac_add_ccx(): subprocess.check_call(command_line, shell=True) # check to see if we have the fortran that ccx needs and return if we do gcc7_to_path = "/usr/local/opt/gcc/lib/gcc/7" + needed_fortran_path = "%s/libgfortran.4.dylib" % gcc7_to_path if os.path.isfile(needed_fortran_path): if os.path.islink(link_to_path): print('Linked gcc7 fortran found and used') else: print('System gcc7 fortran found and used') + print('Finished installing calculix (ccx)') return # install gcc@7 with brew if we don't have it - brew_fortran_path = ("/usr/local/Cellar/gcc@7/7.3.0/lib/gcc/7/" - "libgfortran.4.dylib") - if not os.path.isfile(brew_fortran_path): + paths = glob.glob("/usr/local/Cellar/gcc@7/*") + if not paths: command_line = "brew install gcc@7" subprocess.check_call(command_line, shell=True) print('Installed gcc@7 (needed by calculix)') + paths = glob.glob("/usr/local/Cellar/gcc@7/*") # link gcc@7 from_path to to_path - gcc7_from_path = "/usr/local/Cellar/gcc@7/7.3.0/lib/gcc/7" + gcc7_from_path = "%s/lib/gcc/7" % paths[-1] command_line = "ln -s %s %s" % (gcc7_from_path, gcc7_to_path) subprocess.check_call(command_line, shell=True) + if not os.path.isfile(needed_fortran_path): + raise Exception("Install failed, libgfortran.4.dylib (a library that " + "ccx needs) was NOT FOUND") print('Finished installing calculix (ccx)') diff --git a/pycalculix/partmodule.py b/pycalculix/partmodule.py index ce41944..25e2fb0 100644 --- a/pycalculix/partmodule.py +++ b/pycalculix/partmodule.py @@ -148,14 +148,15 @@ def __set_side(self, side): points = self.points # sort the points low to high points = sorted(points, key=lambda pt: getattr(pt, axis)) - # store the value - val = getattr(points[ind], axis) + # store the target value + target_value = getattr(points[ind], axis) res = [] lines = self.signlines for sline in lines: if isinstance(sline, geometry.SignLine): - vals = [getattr(pt, axis) for pt in sline.points] - if vals == [val, val]: + pt_axis_vals = [getattr(pt, axis) for pt in sline.points] + pt_dist_vals = [abs(target_value - pt_axis_val) for pt_axis_val in pt_axis_vals] + if all([pt_dist_val < geometry.ACC for pt_dist_val in pt_dist_vals]): # line is on the left side res.append(sline) setattr(self, side, res) diff --git a/pycalculix/version.py b/pycalculix/version.py index a82b376..72f26f5 100644 --- a/pycalculix/version.py +++ b/pycalculix/version.py @@ -1 +1 @@ -__version__ = "1.1.1" +__version__ = "1.1.2" diff --git a/tests/test_part.py b/tests/test_part.py new file mode 100644 index 0000000..51d56b2 --- /dev/null +++ b/tests/test_part.py @@ -0,0 +1,131 @@ +import glob +import os +import subprocess +import unittest + +import pycalculix as pyc + +class TestPart(unittest.TestCase): + """Test part module""" + def tearDown(self): + extenstion_to_del = ['fbd', + 'inp', + 'geo', + 'msh', + 'frd', + 'dat', + 'png', + 'cvg', + 'sta', + 'out'] + local_files = glob.glob('*.*') # files that have extensions + for local_file in local_files: + extension = local_file.split('.')[-1] + if extension in extenstion_to_del: + os.unlink(local_file) + + def test_part_sides_perfect(self): + # a hole with multiple lines for each side sets them correctly + proj_name = 'test_part_sides' + + model = pyc.FeaModel(proj_name) + model.set_units('m') # this sets dist units to meters + part = pyc.Part(model) + + divot_width = 1 + corner_width = 2 + + part.goto(0, 0) + left_points = [ + (corner_width, 0), + (corner_width + divot_width, divot_width), + (corner_width + divot_width*2, 0), + (corner_width*2 + divot_width*2, 0), + ] + top_points = [ + (corner_width*2 + divot_width*2, corner_width), + (corner_width*2 + divot_width, corner_width + divot_width), + (corner_width*2 + divot_width*2, corner_width + divot_width*2), + (corner_width*2 + divot_width*2, corner_width*2 + divot_width*2), + ] + right_points = [ + (corner_width + divot_width*2, corner_width*2 + divot_width*2), + (corner_width + divot_width, corner_width*2 + divot_width), + (corner_width, corner_width*2 + divot_width*2), + (0, corner_width*2 + divot_width*2), + ] + bottom_points = [ + (0, corner_width + divot_width*2), + (divot_width, corner_width + divot_width), + (0, corner_width), + (0, 0), + ] + all_points = left_points + top_points + right_points + bottom_points + for x, y in all_points: + part.draw_line_to(x, y) + + self.assertEqual([line.get_name() for line in part.left], ['L0', 'L3']) + self.assertEqual([line.get_name() for line in part.top], ['L4', 'L7']) + self.assertEqual([line.get_name() for line in part.right], ['L8', 'L11']) + self.assertEqual([line.get_name() for line in part.bottom], ['L12', 'L15']) + + def test_part_sides_skewed(self): + # top right point in range, bottom right point out of range + # left side perfet (2 found) + # top in range but skewed on 2nd line (2 found) + # right in range but skewed on 1st line, 2nd out of range (1 found) + # bottom 1st out of range, in range but skewed on 2nd line, 2 (1 found) + initial_accuracy_val = pyc.geometry.ACC + pyc.geometry.ACC = 0.2 + offset_in_range = 0.1 + offset_too_big = 0.4 + + proj_name = 'test_part_sides_skewed' + + model = pyc.FeaModel(proj_name) + model.set_units('m') # this sets dist units to meters + part = pyc.Part(model) + + divot_width = 1 + corner_width = 2 + + part.goto(0, 0) + left_points = [ + (corner_width, 0), + (corner_width + divot_width, divot_width), + (corner_width + divot_width*2, 0), + (corner_width*2 + divot_width*2, 0), + ] + top_points = [ + (corner_width*2 + divot_width*2, corner_width), + (corner_width*2 + divot_width, corner_width + divot_width), + (corner_width*2 + divot_width*2, corner_width + divot_width*2), + ( + corner_width*2 + divot_width*2 - offset_in_range, + corner_width*2 + divot_width*2 - offset_in_range + ), + ] + right_points = [ + (corner_width + divot_width*2, corner_width*2 + divot_width*2), + (corner_width + divot_width, corner_width*2 + divot_width), + (corner_width, corner_width*2 + divot_width*2), + (0 + offset_too_big, corner_width*2 + divot_width*2 - offset_too_big), + ] + bottom_points = [ + (0, corner_width + divot_width*2), + (divot_width, corner_width + divot_width), + (0, corner_width), + (0, 0), + ] + all_points = left_points + top_points + right_points + bottom_points + for x, y in all_points: + part.draw_line_to(x, y) + + self.assertEqual([line.get_name() for line in part.left], ['L0', 'L3']) + self.assertEqual([line.get_name() for line in part.top], ['L4', 'L7']) + self.assertEqual([line.get_name() for line in part.right], ['L8']) + self.assertEqual([line.get_name() for line in part.bottom], ['L15']) + pyc.geometry.ACC = initial_accuracy_val + +if __name__ == '__main__': + unittest.main()