Merge branch 'master' into NthSelector
This commit is contained in:
@ -35,10 +35,15 @@ The original version of CadQuery was built on the FreeCAD API. This was great be
|
||||
|
||||
## Getting started
|
||||
|
||||
To quickly play around with CadQuery and see it's capabilities, see the [CQ-editor GUI](https://github.com/CadQuery/CQ-editor) manual.
|
||||
If you want to use CadQuery for your own project, keep reading:
|
||||
|
||||
It is currently possible to use CadQuery for your own projects in 3 different ways:
|
||||
* Using the [CQ-editor GUI](https://github.com/CadQuery/CQ-editor)
|
||||
* From a [Jupyter notebook](https://github.com/bernhard-42/jupyter-cadquery)
|
||||
* As a standalone library
|
||||
* Linux [installation video](https://youtu.be/sjLTePOq8bQ)
|
||||
* Windows [installation video](https://youtu.be/3Tg_RJhqZRg)
|
||||
|
||||
The easiest way to install CadQuery and its dependencies is using conda, which is included as part of an Anaconda/Miniconda installation. See the next section for an alternative to a full install of Anaconda that may be preferable to some users. The steps to install cadquery are as follows:
|
||||
```
|
||||
|
||||
@ -68,4 +68,4 @@ __all__ = [
|
||||
"plugins",
|
||||
]
|
||||
|
||||
__version__ = "2.1dev"
|
||||
__version__ = "2.1RC1"
|
||||
|
||||
@ -21,15 +21,26 @@ AssemblyObjects = Union[Shape, Workplane, None]
|
||||
ConstraintKinds = Literal["Plane", "Point", "Axis"]
|
||||
ExportLiterals = Literal["STEP", "XML"]
|
||||
|
||||
PATH_DELIM = "/"
|
||||
|
||||
# enitity selector grammar definiiton
|
||||
def _define_grammar():
|
||||
|
||||
from pyparsing import Literal as Literal, Word, Optional, alphas, alphanums
|
||||
from pyparsing import (
|
||||
Literal as Literal,
|
||||
Word,
|
||||
Optional,
|
||||
alphas,
|
||||
alphanums,
|
||||
delimitedList,
|
||||
)
|
||||
|
||||
Separator = Literal("@").suppress()
|
||||
TagSeparator = Literal("?").suppress()
|
||||
|
||||
Name = Word(alphas, alphanums + "_").setResultsName("name")
|
||||
Name = delimitedList(
|
||||
Word(alphas, alphanums + "_"), PATH_DELIM, combine=True
|
||||
).setResultsName("name")
|
||||
Tag = Word(alphas, alphanums + "_").setResultsName("tag")
|
||||
Selector = _selector_grammar.setResultsName("selector")
|
||||
|
||||
@ -234,6 +245,11 @@ class Assembly(object):
|
||||
|
||||
if isinstance(arg, Assembly):
|
||||
|
||||
# enforce unique names
|
||||
name = kwargs["name"] if kwargs.get("name") else arg.name
|
||||
if name in self.objects:
|
||||
raise ValueError("Unique name is required")
|
||||
|
||||
subassy = arg._copy()
|
||||
|
||||
subassy.loc = kwargs["loc"] if kwargs.get("loc") else arg.loc
|
||||
@ -242,11 +258,10 @@ class Assembly(object):
|
||||
subassy.parent = self
|
||||
|
||||
self.children.append(subassy)
|
||||
self.objects[subassy.name] = subassy
|
||||
self.objects.update(subassy.objects)
|
||||
self.objects.update(subassy._flatten())
|
||||
|
||||
else:
|
||||
assy = Assembly(arg, **kwargs)
|
||||
assy = self.__class__(arg, **kwargs)
|
||||
assy.parent = self
|
||||
|
||||
self.add(assy)
|
||||
@ -454,3 +469,17 @@ class Assembly(object):
|
||||
yield el
|
||||
|
||||
yield (self.name, self)
|
||||
|
||||
def _flatten(self, parents=[]):
|
||||
"""
|
||||
Generate a dict with all ancestors with keys indicating parent-child relations.
|
||||
"""
|
||||
|
||||
rv = {}
|
||||
|
||||
for ch in self.children:
|
||||
rv.update(ch._flatten(parents=parents + [self.name]))
|
||||
|
||||
rv[PATH_DELIM.join(parents + [self.name])] = self
|
||||
|
||||
return rv
|
||||
|
||||
@ -1746,6 +1746,7 @@ class Workplane(object):
|
||||
N: int = 400,
|
||||
start: float = 0,
|
||||
stop: float = 1,
|
||||
makeWire: bool = True,
|
||||
) -> "Workplane":
|
||||
"""
|
||||
Create a spline interpolated through the provided points.
|
||||
@ -1755,6 +1756,7 @@ class Workplane(object):
|
||||
:param N: number of points for discretization
|
||||
:param start: starting value of the parameter t
|
||||
:param stop: final value of the parameter t
|
||||
:param makeWire: convert the resulting spline edge to a wire
|
||||
:return: a Workplane object with the current point unchanged
|
||||
|
||||
"""
|
||||
@ -1762,7 +1764,7 @@ class Workplane(object):
|
||||
diff = stop - start
|
||||
allPoints = [func(start + diff * t / N) for t in range(N + 1)]
|
||||
|
||||
return self.spline(allPoints, includeCurrent=False, makeWire=True)
|
||||
return self.spline(allPoints, includeCurrent=False, makeWire=makeWire)
|
||||
|
||||
def ellipseArc(
|
||||
self,
|
||||
|
||||
63
changes.md
63
changes.md
@ -3,9 +3,70 @@ Changes
|
||||
|
||||
Master
|
||||
------
|
||||
### Breaking changes
|
||||
### Breaking changes
|
||||
* Fixed bug in ParallelDirSelector where non-planar faces could be selected. Note this will be breaking if you've used DirectionNthSelector and a non-planar face made it into your object list. In that case eg. ">X[2]" will have to become ">X[1]".
|
||||
|
||||
2.1RC1 (release candidate)
|
||||
------
|
||||
### Breaking changes
|
||||
* `centerOption` default value changed from `CenterOfMass` to `ProjectedOrigin` #532
|
||||
|
||||
## Other changes
|
||||
|
||||
* Simplified `largestDimension()` bounding box check #317
|
||||
* Added `FontPath` to `makeText()` #337
|
||||
* Support for slicing (`section()`) of models #339 #349
|
||||
* Added DXF import (relies on ezdxf) #351 #372 #406 #442
|
||||
* Added DXF export #415 #419 #455
|
||||
* Exposed `angularPrecision` parameter in `exportStl()` #329
|
||||
* Fixed bug in `makeRuled()` #329
|
||||
* Made solid construction from `shell()` more robust #329
|
||||
* Added CadQuery logos to docs #329
|
||||
* Added `toPending()` to allow adding wires/edges to `pendingWires`/`pendingEdges` #351
|
||||
* Implemented `glue` parameter for `fuse()` #375
|
||||
* Exposed parameters for fuzzy bool operations #375
|
||||
* Started using MyPy in CI and type annotations #378 #380 #391
|
||||
* Implemented a `Location` class #380
|
||||
* Merged `CQ` class into `Workplane` to eliminate duplicated code #380
|
||||
* Added additional parameters for `BuildCurves3d_s` method #387
|
||||
* Implemented fully closed shelling #394
|
||||
* Refactored `polarArray()` #395
|
||||
* Improved local rotation handling #395
|
||||
* Implemented 2D offset in `offset2D` #397
|
||||
* Added `locationAt()` to generate locations along a curve #404
|
||||
* Added DOI to README for references in research papers #412
|
||||
* Changed `shell()` to set `Intersection` parameter to `True` #411
|
||||
* Exposed joint type (`kind`) for `shell()` #413
|
||||
* Refactored exporters #415
|
||||
* Started using `find_packages()` in setup.py #418
|
||||
* Tessellation winding fix #420
|
||||
* Added `angularPrecision` to `export`, `exportShape` and `toString` #424
|
||||
* Added py.typed file for PEP-561 compatibility #435
|
||||
* Added assembly API with constraint solver #440 #482 #545 #556
|
||||
* Integrated sphinxcadquery to add 3D visualization of parts to docs #111
|
||||
* Allow spaces in Vector literal #445
|
||||
* Added export to OCCT native CAF format #440
|
||||
* Implemented color export in STEP generated from assemblies #440
|
||||
* Added ability to set `fontPath` parameter for `text()` #453
|
||||
* Now protect against `rarray()` spacings of 0 #454
|
||||
* Changed Nth selector rounding `self.TOLERANCE` calculation to produce 4 decimal places #461
|
||||
* Fixed `parametricCurve()` to use correct stop point #477
|
||||
* Excluded tests from installation in setup.py #478
|
||||
* Added `mesh()` method to shapes.py #482
|
||||
* Added VRML export #482
|
||||
* Implemented ability to create a child workplane on the vertex #480
|
||||
* Improved consistency in handling of BoundaryBox tolerance #490
|
||||
* Implemented `locations()` for Wires #475
|
||||
* Exposed mode for sweep operations #496
|
||||
* Added 'RadiusNthSelector()` #504
|
||||
* Added tag-based constraint definition for assemblies #514
|
||||
* Implemented ability to mirror from a selected face #527
|
||||
* Improved edge selector tests #541
|
||||
* Added `glue` parameter to `combine()` #535
|
||||
* Finally fixed github-linguist statistics #547
|
||||
* Updated for Python 3.8
|
||||
* Numerous documentation updates and example additions
|
||||
|
||||
2.0 (stable release)
|
||||
------
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ Next we want to define functions generating the assembly components based on the
|
||||
.workplane()
|
||||
.cboreHole(6, 15, 18)
|
||||
.faces("<Z")
|
||||
.workplane()
|
||||
.workplane(centerOption="CenterOfMass")
|
||||
.cboreHole(6, 15, 18)
|
||||
)
|
||||
|
||||
@ -238,7 +238,7 @@ Below is the complete code including the final solve step.
|
||||
.workplane()
|
||||
.cboreHole(6, 15, 18)
|
||||
.faces("<Z")
|
||||
.workplane()
|
||||
.workplane(centerOption="CenterOfMass")
|
||||
.cboreHole(6, 15, 18)
|
||||
)
|
||||
|
||||
|
||||
2
setup.py
2
setup.py
@ -16,7 +16,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
|
||||
# if we are building in travis, use the build number as the sub-minor version
|
||||
version = "2.1dev"
|
||||
version = "2.1RC1"
|
||||
if "TRAVIS_TAG" in os.environ.keys():
|
||||
version = os.environ["TRAVIS_TAG"]
|
||||
|
||||
|
||||
@ -153,8 +153,8 @@ def test_constrain(simple_assy, nested_assy):
|
||||
|
||||
assert len(simple_assy.constraints) == 3
|
||||
|
||||
nested_assy.constrain("TOP@faces@>Z", "BOTTOM@faces@<Z", "Plane")
|
||||
nested_assy.constrain("TOP@faces@>X", "BOTTOM@faces@<X", "Axis")
|
||||
nested_assy.constrain("TOP@faces@>Z", "SECOND/BOTTOM@faces@<Z", "Plane")
|
||||
nested_assy.constrain("TOP@faces@>X", "SECOND/BOTTOM@faces@<X", "Axis")
|
||||
|
||||
assert len(nested_assy.constraints) == 2
|
||||
|
||||
@ -168,7 +168,7 @@ def test_constrain(simple_assy, nested_assy):
|
||||
.IsEqual(gp_XYZ(), 1e-9)
|
||||
)
|
||||
assert constraint.sublocs[1].wrapped.IsEqual(
|
||||
nested_assy.objects["BOTTOM"].loc.wrapped
|
||||
nested_assy.objects["SECOND/BOTTOM"].loc.wrapped
|
||||
)
|
||||
|
||||
simple_assy.solve()
|
||||
@ -199,10 +199,16 @@ def test_constrain(simple_assy, nested_assy):
|
||||
def test_constrain_with_tags(nested_assy):
|
||||
|
||||
nested_assy.add(None, name="dummy")
|
||||
nested_assy.constrain("TOP?top_face", "BOTTOM", "Plane")
|
||||
nested_assy.constrain("TOP?top_face", "SECOND/BOTTOM", "Plane")
|
||||
|
||||
assert len(nested_assy.constraints) == 1
|
||||
|
||||
# test selection of a non-shape object
|
||||
with pytest.raises(ValueError):
|
||||
nested_assy.constrain("BOTTOM ? pts", "dummy", "Plane")
|
||||
nested_assy.constrain("SECOND/BOTTOM ? pts", "dummy", "Plane")
|
||||
|
||||
|
||||
def test_duplicate_name(nested_assy):
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
nested_assy.add(None, name="SECOND")
|
||||
|
||||
Reference in New Issue
Block a user