Merge branch 'master' into NthSelector

This commit is contained in:
Adam Urbańczyk
2021-01-03 15:48:02 +01:00
committed by GitHub
8 changed files with 120 additions and 17 deletions

View File

@ -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:
```

View File

@ -68,4 +68,4 @@ __all__ = [
"plugins",
]
__version__ = "2.1dev"
__version__ = "2.1RC1"

View File

@ -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

View File

@ -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,

View File

@ -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)
------

View File

@ -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)
)

View File

@ -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"]

View File

@ -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")