Updated the CadQuery library for the addition of multi-sweep.
This commit is contained in:
parent
00e6fb8d5c
commit
1194b9ee42
7
Libs/cadquery/.coveragerc
Normal file
7
Libs/cadquery/.coveragerc
Normal file
|
@ -0,0 +1,7 @@
|
|||
[run]
|
||||
include = cadquery/*
|
||||
omit = cadquery/cq_directive.py
|
||||
|
||||
|
||||
[xml]
|
||||
output = coverage.xml
|
|
@ -4,7 +4,6 @@ matrix:
|
|||
include:
|
||||
- python: 2.7
|
||||
- python: 3.6
|
||||
env: FREECAD_LIB="$HOME/miniconda/envs/freecad_cq3/lib/"
|
||||
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" == "3.6" ]]; then
|
||||
|
@ -15,7 +14,7 @@ before_install:
|
|||
conda config --set always_yes yes --set changeps1 no;
|
||||
conda update -q conda;
|
||||
conda info -a;
|
||||
conda create -y -q -n freecad_cq3 -c freecad -c conda-forge freecad=0.17=py36_11 occt=7.2.0=occt7.2.0_0 python=3.6 pyparsing conda mock;
|
||||
conda create -y -q -n freecad_cq3 -c freecad -c freecad/label/broken -c conda-forge freecad=0.17=py36_11 occt=7.2.0=occt7.2.0_0 python=3.6 pyparsing conda mock coverage codecov;
|
||||
source ~/miniconda/bin/activate freecad_cq3;
|
||||
else
|
||||
sudo add-apt-repository -y ppa:freecad-maintainers/freecad-stable;
|
||||
|
@ -30,11 +29,14 @@ install:
|
|||
- python setup.py install;
|
||||
|
||||
script:
|
||||
- coverage run runtests.py
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
||||
coverage run --source=cadquery --omit=cadquery/cq_directive.py ./runtests.py;
|
||||
travis-sphinx build --nowarn --source=doc;
|
||||
fi
|
||||
- python runtests.py
|
||||
|
||||
after_success:
|
||||
- coverage xml
|
||||
- codecov -X gcov --file coverage.xml
|
||||
|
||||
after_script:
|
||||
- coveralls
|
||||
|
@ -44,6 +46,7 @@ branches:
|
|||
except:
|
||||
- pythonocc
|
||||
- 2_0_branch
|
||||
|
||||
deploy:
|
||||
provider: pypi
|
||||
user: dcowden
|
||||
|
|
|
@ -6,6 +6,7 @@ What is a CadQuery?
|
|||
========================================
|
||||
|
||||
[](https://travis-ci.org/dcowden/cadquery?branch=master)
|
||||
[](https://ci.appveyor.com/project/jmwright/cadquery/branch/master)
|
||||
[](https://coveralls.io/github/dcowden/cadquery?branch=master)
|
||||
[](https://github.com/dcowden/cadquery/releases/tag/v1.1.0)
|
||||
[](https://github.com/dcowden/cadquery/blob/master/LICENSE)
|
||||
|
|
26
Libs/cadquery/appveyor.yml
Normal file
26
Libs/cadquery/appveyor.yml
Normal file
|
@ -0,0 +1,26 @@
|
|||
shallow_clone: true
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- PYTHON_VERSION: 3.6
|
||||
MINICONDA_DIRNAME: C:\Miniconda36-x64
|
||||
|
||||
install:
|
||||
- set "PATH=%MINICONDA_DIRNAME%;%MINICONDA_DIRNAME%\\Scripts;%PATH%"
|
||||
- conda config --set always_yes yes
|
||||
- conda update -q conda
|
||||
- conda create --quiet --name cqtest -c freecad -c freecad/label/broken -c conda-forge python=%PYTHON_VERSION% freecad=0.17=py36_vc14_13 occt=7.2.0 python=3.6 pyparsing mock coverage codecov
|
||||
- activate cqtest
|
||||
- python setup.py install
|
||||
|
||||
build: false
|
||||
|
||||
test_script:
|
||||
- coverage run runtests.py
|
||||
|
||||
on_success:
|
||||
- coverage xml
|
||||
- codecov -X gcov --file coverage.xml
|
|
@ -2073,17 +2073,20 @@ class Workplane(CQ):
|
|||
if clean: newS = newS.clean()
|
||||
return newS
|
||||
|
||||
def sweep(self, path, makeSolid=True, isFrenet=False, combine=True, clean=True):
|
||||
def sweep(self, path, sweepAlongWires=False, makeSolid=True, isFrenet=False, combine=True, clean=True):
|
||||
"""
|
||||
Use all un-extruded wires in the parent chain to create a swept solid.
|
||||
|
||||
:param path: A wire along which the pending wires will be swept
|
||||
:param boolean sweepAlongWires:
|
||||
False to create mutliple swept from wires on the chain along path
|
||||
True to create only one solid swept along path with shape following the list of wires on the chain
|
||||
:param boolean combine: True to combine the resulting solid with parent solids if found.
|
||||
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
|
||||
:return: a CQ object with the resulting solid selected.
|
||||
"""
|
||||
|
||||
r = self._sweep(path.wire(), makeSolid, isFrenet) # returns a Solid (or a compound if there were multiple)
|
||||
r = self._sweep(path.wire(), sweepAlongWires, makeSolid, isFrenet) # returns a Solid (or a compound if there were multiple)
|
||||
if combine:
|
||||
newS = self._combineWithBase(r)
|
||||
else:
|
||||
|
@ -2397,11 +2400,14 @@ class Workplane(CQ):
|
|||
|
||||
return Compound.makeCompound(toFuse)
|
||||
|
||||
def _sweep(self, path, makeSolid=True, isFrenet=False):
|
||||
def _sweep(self, path, sweepAlongWires=False, makeSolid=True, isFrenet=False):
|
||||
"""
|
||||
Makes a swept solid from an existing set of pending wires.
|
||||
|
||||
:param path: A wire along which the pending wires will be swept
|
||||
:param boolean sweepAlongWires:
|
||||
False to create mutliple swept from wires on the chain along path
|
||||
True to create only one solid swept along path with shape following the list of wires on the chain
|
||||
:return:a FreeCAD solid, suitable for boolean operations
|
||||
"""
|
||||
|
||||
|
@ -2413,8 +2419,20 @@ class Workplane(CQ):
|
|||
self.ctx.pendingWires = [] # now all of the wires have been used to create an extrusion
|
||||
|
||||
toFuse = []
|
||||
for ws in wireSets:
|
||||
thisObj = Solid.sweep(ws[0], ws[1:], path.val(), makeSolid, isFrenet)
|
||||
if not sweepAlongWires:
|
||||
for ws in wireSets:
|
||||
thisObj = Solid.sweep(ws[0], ws[1:], path.val(), makeSolid, isFrenet)
|
||||
toFuse.append(thisObj)
|
||||
else:
|
||||
section = []
|
||||
for ws in wireSets:
|
||||
for i in range(0, len(ws)):
|
||||
section.append(ws[i])
|
||||
|
||||
# implementation
|
||||
outW = Wire(section[0].wrapped)
|
||||
inW = section[1:]
|
||||
thisObj = Solid.sweep(outW, inW, path.val(), makeSolid, isFrenet)
|
||||
toFuse.append(thisObj)
|
||||
|
||||
return Compound.makeCompound(toFuse)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"""
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
|
||||
|
||||
#FreeCAD has crudified the stdout stream with a bunch of STEP output
|
||||
|
@ -60,6 +61,19 @@ def _fc_path():
|
|||
if _PATH and os.path.exists(_PATH):
|
||||
return _PATH
|
||||
|
||||
# Try to guess if using Anaconda
|
||||
if 'env' in sys.prefix:
|
||||
if sys.platform.startswith('linux'):
|
||||
_PATH = os.path.join(sys.prefix,'lib')
|
||||
# return PATH if FreeCAD.[so,pyd] is present
|
||||
if len(glob.glob(os.path.join(_PATH,'FreeCAD.so'))) > 0:
|
||||
return _PATH
|
||||
elif sys.platform.startswith('win'):
|
||||
_PATH = os.path.join(sys.prefix,'Library','bin')
|
||||
# return PATH if FreeCAD.[so,pyd] is present
|
||||
if len(glob.glob(os.path.join(_PATH,'FreeCAD.pyd'))) > 0:
|
||||
return _PATH
|
||||
|
||||
if sys.platform.startswith('linux'):
|
||||
# Make some dangerous assumptions...
|
||||
for _PATH in [
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import cadquery as cq
|
||||
|
||||
# X axis line length 20.0
|
||||
path = cq.Workplane("XZ").moveTo(-10, 0).lineTo(10, 0)
|
||||
|
||||
# Sweep a circle from diameter 2.0 to diameter 1.0 to diameter 2.0 along X axis length 10.0 + 10.0
|
||||
defaultSweep = cq.Workplane("YZ").workplane(offset=-10.0).circle(2.0). \
|
||||
workplane(offset=10.0).circle(1.0). \
|
||||
workplane(offset=10.0).circle(2.0).sweep(path, sweepAlongWires=True)
|
||||
|
||||
# We can sweep thrue different shapes
|
||||
recttocircleSweep = cq.Workplane("YZ").workplane(offset=-10.0).rect(2.0, 2.0). \
|
||||
workplane(offset=8.0).circle(1.0).workplane(offset=4.0).circle(1.0). \
|
||||
workplane(offset=8.0).rect(2.0, 2.0).sweep(path, sweepAlongWires=True)
|
||||
|
||||
circletorectSweep = cq.Workplane("YZ").workplane(offset=-10.0).circle(1.0). \
|
||||
workplane(offset=7.0).rect(2.0, 2.0).workplane(offset=6.0).rect(2.0, 2.0). \
|
||||
workplane(offset=7.0).circle(1.0).sweep(path, sweepAlongWires=True)
|
||||
|
||||
|
||||
# Placement of the Shape is important otherwise could produce unexpected shape
|
||||
specialSweep = cq.Workplane("YZ").circle(1.0).workplane(offset=10.0).rect(2.0, 2.0). \
|
||||
sweep(path, sweepAlongWires=True)
|
||||
|
||||
# Switch to an arc for the path : line l=5.0 then half circle r=4.0 then line l=5.0
|
||||
path = cq.Workplane("XZ").moveTo(-5, 4).lineTo(0, 4). \
|
||||
threePointArc((4, 0), (0, -4)).lineTo(-5, -4)
|
||||
|
||||
# Placement of different shapes should follow the path
|
||||
# cylinder r=1.5 along first line
|
||||
# then sweep allong arc from r=1.5 to r=1.0
|
||||
# then cylinder r=1.0 along last line
|
||||
arcSweep = cq.Workplane("YZ").workplane(offset=-5).moveTo(0, 4).circle(1.5). \
|
||||
workplane(offset=5).circle(1.5). \
|
||||
moveTo(0, -8).circle(1.0). \
|
||||
workplane(offset=-5).circle(1.0). \
|
||||
sweep(path, sweepAlongWires=True)
|
||||
|
||||
|
||||
# Translate the resulting solids so that they do not overlap and display them left to right
|
||||
show_object(defaultSweep)
|
||||
show_object(circletorectSweep.translate((0, 5, 0)))
|
||||
show_object(recttocircleSweep.translate((0, 10, 0)))
|
||||
show_object(specialSweep.translate((0, 15, 0)))
|
||||
show_object(arcSweep.translate((0, -5, 0)))
|
||||
|
||||
|
|
@ -5,3 +5,4 @@ coverage
|
|||
coveralls
|
||||
pyparsing
|
||||
mock
|
||||
codecov
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import os
|
||||
import codecs
|
||||
from setuptools import setup
|
||||
|
||||
|
||||
|
@ -29,7 +30,7 @@ setup(
|
|||
author='David Cowden',
|
||||
author_email='dave.cowden@gmail.com',
|
||||
description='CadQuery is a parametric scripting language for creating and traversing CAD models',
|
||||
long_description=open('README.md').read(),
|
||||
long_description=codecs.open('README.md', 'rb', 'UTF-8').read(),
|
||||
packages=['cadquery','cadquery.contrib','cadquery.freecad_impl','cadquery.plugins','tests'],
|
||||
install_requires=['pyparsing'],
|
||||
include_package_data=True,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
"""
|
||||
#system modules
|
||||
import math,sys,os.path,time
|
||||
import math,os.path,time,tempfile
|
||||
|
||||
#my modules
|
||||
from cadquery import *
|
||||
|
@ -19,11 +19,7 @@ from tests import (
|
|||
from cadquery.freecad_impl import suppress_stdout_stderr
|
||||
|
||||
#where unit test output will be saved
|
||||
import sys
|
||||
if sys.platform.startswith("win"):
|
||||
OUTDIR = "c:/temp"
|
||||
else:
|
||||
OUTDIR = "/tmp"
|
||||
OUTDIR = tempfile.gettempdir()
|
||||
SUMMARY_FILE = os.path.join(OUTDIR,"testSummary.html")
|
||||
|
||||
SUMMARY_TEMPLATE="""<html>
|
||||
|
@ -449,6 +445,54 @@ class TestCadQuery(BaseTest):
|
|||
self.assertEqual(3, result.faces().size())
|
||||
self.assertEqual(3, result.edges().size())
|
||||
|
||||
def testSweepAlongListOfWires(self):
|
||||
"""
|
||||
Tests the operation of sweeping along a list of wire(s) along a path
|
||||
"""
|
||||
|
||||
# X axis line length 20.0
|
||||
path = Workplane("XZ").moveTo(-10, 0).lineTo(10, 0)
|
||||
|
||||
# Sweep a circle from diameter 2.0 to diameter 1.0 to diameter 2.0 along X axis length 10.0 + 10.0
|
||||
defaultSweep = Workplane("YZ").workplane(offset=-10.0).circle(2.0). \
|
||||
workplane(offset=10.0).circle(1.0). \
|
||||
workplane(offset=10.0).circle(2.0).sweep(path, sweepAlongWires=True)
|
||||
|
||||
# We can sweep thrue different shapes
|
||||
recttocircleSweep = Workplane("YZ").workplane(offset=-10.0).rect(2.0, 2.0). \
|
||||
workplane(offset=8.0).circle(1.0).workplane(offset=4.0).circle(1.0). \
|
||||
workplane(offset=8.0).rect(2.0, 2.0).sweep(path, sweepAlongWires=True)
|
||||
|
||||
circletorectSweep = Workplane("YZ").workplane(offset=-10.0).circle(1.0). \
|
||||
workplane(offset=7.0).rect(2.0, 2.0).workplane(offset=6.0).rect(2.0, 2.0). \
|
||||
workplane(offset=7.0).circle(1.0).sweep(path, sweepAlongWires=True)
|
||||
|
||||
# Placement of the Shape is important otherwise could produce unexpected shape
|
||||
specialSweep = Workplane("YZ").circle(1.0).workplane(offset=10.0).rect(2.0, 2.0). \
|
||||
sweep(path, sweepAlongWires=True)
|
||||
|
||||
# Switch to an arc for the path : line l=5.0 then half circle r=4.0 then line l=5.0
|
||||
path = Workplane("XZ").moveTo(-5, 4).lineTo(0, 4). \
|
||||
threePointArc((4, 0), (0, -4)).lineTo(-5, -4)
|
||||
|
||||
# Placement of different shapes should follow the path
|
||||
# cylinder r=1.5 along first line
|
||||
# then sweep allong arc from r=1.5 to r=1.0
|
||||
# then cylinder r=1.0 along last line
|
||||
arcSweep = Workplane("YZ").workplane(offset=-5).moveTo(0, 4).circle(1.5). \
|
||||
workplane(offset=5).circle(1.5). \
|
||||
moveTo(0, -8).circle(1.0). \
|
||||
workplane(offset=-5).circle(1.0). \
|
||||
sweep(path, sweepAlongWires=True)
|
||||
|
||||
# Test and saveModel
|
||||
self.assertEqual(1, defaultSweep.solids().size())
|
||||
self.assertEqual(1, circletorectSweep.solids().size())
|
||||
self.assertEqual(1, recttocircleSweep.solids().size())
|
||||
self.assertEqual(1, specialSweep.solids().size())
|
||||
self.assertEqual(1, arcSweep.solids().size())
|
||||
self.saveModel(defaultSweep)
|
||||
|
||||
def testTwistExtrude(self):
|
||||
"""
|
||||
Tests extrusion while twisting through an angle.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Tests file importers such as STEP
|
||||
"""
|
||||
#core modules
|
||||
import io
|
||||
import tempfile
|
||||
|
||||
from cadquery import *
|
||||
from cadquery import exporters
|
||||
|
@ -11,12 +11,7 @@ from cadquery.freecad_impl import suppress_stdout_stderr
|
|||
from tests import BaseTest
|
||||
|
||||
#where unit test output will be saved
|
||||
import sys
|
||||
if sys.platform.startswith("win"):
|
||||
OUTDIR = "c:/temp"
|
||||
else:
|
||||
OUTDIR = "/tmp"
|
||||
|
||||
OUTDIR = tempfile.gettempdir()
|
||||
|
||||
class TestImporters(BaseTest):
|
||||
def importBox(self, importType, fileName):
|
||||
|
|
Loading…
Reference in New Issue
Block a user