Skip to content

Commit

Permalink
Merge pull request #15 from gumyr/dev
Browse files Browse the repository at this point in the history
Release 0.5.0 Content
  • Loading branch information
gumyr authored Jan 22, 2022
2 parents 23265df + 7fd97d0 commit d63fbc3
Show file tree
Hide file tree
Showing 15 changed files with 2,676 additions and 22 deletions.
283 changes: 281 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,37 @@ or CAM systems.
- [Assembly class extensions](#assembly-class-extensions)
- [Translate](#translate)
- [Rotate](#rotate)
- [Plane class extensions](#plane-class-extensions)
- [Transform to Local Coordinates](#transform-to-local-coordinates)
- [Vector class extensions](#vector-class-extensions)
- [Rotate about X,Y and Z Axis](#rotate-about-xy-and-z-axis)
- [Map 2D Vector to 3D Vector](#map-2d-vector-to-3d-vector)
- [Translate to Vertex](#translate-to-vertex)
- [Get Signed Angle between Vectors](#get-signed-angle-between-vectors)
- [Vertex class extensions](#vertex-class-extensions)
- [Add](#add)
- [Subtract](#subtract)
- [Display](#display)
- [Convert to Vector](#convert-to-vector)
- [Workplane class extensions](#workplane-class-extensions)
- [Text on 2D Path](#text-on-2d-path)
- [Hex Array](#hex-array)
- [Thicken Non-Planar Face](#thicken-non-planar-face)
- [Face class extensions](#face-class-extensions)
- [Thicken](#thicken)
- [Project Face to Shape](#project-face-to-shape)
- [Emboss Face To Shape](#emboss-face-to-shape)
- [Wire class extensions](#wire-class-extensions)
- [Make Non Planar Face](#make-non-planar-face)
- [Project Wire to Shape](#project-wire-to-shape)
- [Emboss Wire to Shape](#emboss-wire-to-shape)
- [Edge class extensions](#edge-class-extensions)
- [Project Edge to Shape](#project-edge-to-shape)
- [Emboss Edge to Shape](#emboss-edge-to-shape)
- [Shape class extensions](#shape-class-extensions)
- [Find Intersection](#find-intersection)
- [Project Text on Shape](#project-text-on-shape)
- [Emboss Text on Shape](#emboss-text-on-shape)
# Installation
Install from github:
```
Expand Down Expand Up @@ -871,6 +894,10 @@ The 'short' and 'long' values from the first table (not shown) control the minim
- **New Fastener Types** - The base/derived class structure was designed to allow the creation of new fastener types/classes. For new fastener classes a 2D drawing of one half of the fastener profile is required. If the fastener has a non circular plan (e.g. a hex or a square) a 2D drawing of the plan is required. If the fastener contains a flange and a plan, a 2D profile of the flange is required. If these profiles or plans are present, the base class will use them to build the fastener. The Abstract Base Class technology ensures derived classes can't be created with missing components.
## extensions sub-package
This python module provides extensions to the native cadquery code base. Hopefully future generations of cadquery will incorporate this or similar functionality.

Examples illustrating how to use much of the functionality of this sub-package can be found in the [extensions_examples.py](examples/extensions_examples.py) file.

To help the user in debugging exceptions generated by the Opencascade core, the dreaded `StdFail_NotDone` exception is caught and augmented with a more meaningful exception where possible (a new exception is raised from StdFail_NotDone so no information is lost). In addition, python logging is used internally which can be enabled (currently by un-commenting the logging configuration code) to provide run-time information in a `cq_warehouse.log` file.
### Assembly class extensions
Two additional methods are added to the `Assembly` class which allow easy manipulation of an Assembly like the chain cadquery objects.
#### Translate
Expand All @@ -888,7 +915,15 @@ Assembly.rotate(self, axis: VectorLike, angle: float):
:param angle: the rotation angle, in degrees
:type angle: float
```

### Plane class extensions
#### Transform to Local Coordinates
Adding the ability to transform a Bounding Box.
```python
Plane.toLocalCoords(self, obj)
:param obj: an object, vector, or bounding box to convert
:type Vector, Shape, or BoundBox
:return: an object of the same type, but converted to local coordinates
```
### Vector class extensions
Methods to rotate a `Vector` about an axis and to convert a 2D point to 3D space.
#### Rotate about X,Y and Z Axis
Expand All @@ -908,6 +943,16 @@ Vector.pointToVector(self, plane: str, offset: float = 0.0) -> cq.Vector
:param offset: The distance from the origin to the provided plane
:type offset: float
```
#### Translate to Vertex
Convert a Vector to a Vertex
```python
Vector.toVertex() -> Vector
```
#### Get Signed Angle between Vectors
Return the angle between two vectors on a plane with the given normal, where angle = atan2((Va x Vb) . Vn, Va . Vb) - in RADIANS.
```python
Vector.getSignedAngle(v: Vector, normal: Vector = None) -> float
```

### Vertex class extensions
To facilitate placement of drafting objects within a design the cadquery `Vertex` class has been extended with addition and subtraction methods so control points can be defined as follows:
Expand Down Expand Up @@ -943,4 +988,238 @@ Vertex.__str__(self) -> str:
Convert a Vertex to a Vector
```python
Vertex.toVector(self) -> cq.Vector:
```
```

### Workplane class extensions

#### Text on 2D Path
Place 2D/3D text on a 2D path as follows:
![textOnPath](doc/textOnPath.png)

```python
Workplane.textOnPath(
txt: str,
fontsize: float,
distance: float,
start: float = 0.0,
cut: bool = True,
combine: bool = False,
clean: bool = True,
font: str = "Arial",
fontPath: Optional[str] = None,
kind: Literal["regular", "bold", "italic"] = "regular",
valign: Literal["center", "top", "bottom"] = "center",
)
```
The parameters are largely the same as the `Workplane.text` method. The `start` parameter (normally between 0.0 and 1.0) specify where on the path to start the text.

Here are two examples:
```python
fox = (
cq.Workplane("XZ")
.threePointArc((50, 30), (100, 0))
.textOnPath(
txt="The quick brown fox jumped over the lazy dog",
fontsize=5,
distance=1,
start=0.1,
)
)
clover = (
cq.Workplane("front")
.moveTo(0, 10)
.radiusArc((10, 0), 7.5)
.radiusArc((0, -10), 7.5)
.radiusArc((-10, 0), 7.5)
.radiusArc((0, 10), 7.5)
.consolidateWires()
.textOnPath(
txt=".x" * 102,
fontsize=1,
distance=1,
)
)
```
The path that the text follows is defined by the last Edge or Wire in the Workplane stack. Path's defined outside of the Workplane can be used with the `.add(path)` method.

#### Hex Array
Create a set of points on the stack which describe a hexagon array or honeycomb and push them onto the stack.
```python
Workplane.hexArray(
diagonal: float,
xCount: int,
yCount: int,
center: Union[bool, tuple[bool, bool]] = True,
):
:param diagonal: tip to tip size of hexagon ( must be > 0)
:param xCount: number of points ( > 0 )
:param yCount: number of points ( > 0 )
:param center: If True, the array will be centered around the workplane center. If False, the lower corner will be on the reference point and the array will extend in the positive x and y directions. Can also use a 2-tuple to specify centering along each axis.
```
#### Thicken Non-Planar Face
Find all of the faces on the stack and make them Solid objects by thickening along the normals.
```python
Workplane.thicken(depth: float, direction: cq.Vector = None)
:param depth: the amount to thicken - can be positive or negative
:param direction: an optional 'which way is up' parameter that ensures a set of faces are thickened in the same direction.
```

### Face class extensions

#### Thicken
Create a solid from a potentially non planar face by thickening along the normals. The direction vector can be used to indicate which way is 'up', potentially flipping the face normal direction such that many faces with different normals all go in the same direction (direction need only be +/- 90 degrees from the face normal.)

In the following example, non-planar faces are thickened both towards and away from the center of the sphere.
![thickenFace](doc/thickenFace.png)
```python
Face.thicken(depth: float, direction: cq.Vector = None) -> cq.Solid
:param depth: the amount to thicken - can be positive or negative
:param direction: an optional 'which way is up' parameter that ensures a set of faces are thickened in the same direction.
```

#### Project Face to Shape
Project a Face onto a Shape generating new Face(s) on the surfaces of the object. Two types of projections are supported, a parallel or flat projection with a `direction` indicator or a conical projection where a `center` must be provided.

The two types of projections are illustrated below:

![flatProjection](doc/flatProjection.png)
![conicalProjection](doc/conicalProjection.png)

The API is as follows:
```python
Face.projectFaceToShape(
targetObject: cq.Shape,
direction: VectorLike = None,
center: VectorLike = None,
internalFacePoints: list[cq.Vector] = [],
) -> list[cq.Face]
```
Note that an array of Faces is returned as the projection might result in faces on the "front" and "back" of the object (or even more if there are intermediate surfaces in the projection path). Faces "behind" the projection are not returned.

To help refine the resulting face, a list of planar points can be passed to augment the surface definition. For example, when projecting a circle onto a sphere, a circle will result which will get converted to a planar circle face. If no points are provided, a single center point will be generated and used for this purpose.

#### Emboss Face To Shape
Emboss a Face defined on the XY plane to the Shape. Unlike projection, emboss attempts to maintain the lengths of the edges defining the face.

```python
Face.embossFaceToShape(
targetObject: cq.Shape,
surfacePoint: VectorLike,
surfaceXDirection: VectorLike,
internalFacePoints: list[cq.Vector] = [],
) -> cq.Face
```
Unlike projection, a single Face is returned. The internalFacePoints parameter works as with projection.

### Wire class extensions

#### Make Non Planar Face
Create a potentially non-planar face bounded by exterior (wire or edges), optionally refined by surfacePoints with optional holes defined by interiorWires.

```python
def makeNonPlanarFace(
exterior: Union[cq.Wire, list[cq.Edge]],
surfacePoints: list[VectorLike] = None,
interiorWires: list[cq.Wire] = None,
) -> cq.Face
```
or
```python
Wire.makeNonPlanarFace(
surfacePoints: list[VectorLike] = None,
interiorWires: list[cq.Wire] = None,
) -> cq.Face
```
The `surfacePoints` parameter can be used to refine the resulting Face. If no points are provided a single central point will be used to help avoid the creation of a planar face.

The `interiorWires` parameter can be used to pass one or more wires which define holes in the Face.

#### Project Wire to Shape
Project a Wire onto a Shape generating new Wires on the surfaces of the object one and only one of `direction` or `center` must be provided. Note that one more more wires may be generated depending on the topology of the target object and location/direction of projection.

```python
Wire.projectWireToShape(
targetObject: cq.Shape,
direction: VectorLike = None,
center: VectorLike = None,
) -> list[cq.Wire]
```

#### Emboss Wire to Shape
Emboss a planar Wire defined on the XY plane to targetObject maintaining the length while doing so. An illustration follows:

![embossWire](doc/embossWire.png)

The embossed wire can be used to build features as:

![embossFeature](doc/embossFeature.png)

with the `sweep` method.

```python
Wire.embossWireToShape(
targetObject: cq.Shape,
surfacePoint: VectorLike,
surfaceXDirection: VectorLike,
tolerance: float = 0.01,
) -> cq.Wire
```
The `surfacePoint` defines where on the target object the wire will be embossed while the `surfaceXDirection` controls the orientation of the wire on the surface. The `tolerance` parameter controls the accuracy of the embossed wire's length.

### Edge class extensions

#### Project Edge to Shape
Same as [Project Wire To Shape](#project_wire-to-shape)


#### Emboss Edge to Shape
Same as [Emboss Wire To Shape](#emboss_wire-to-shape)

### Shape class extensions

#### Find Intersection
Return both the point(s) and normal(s) of the intersection of the line (defined by a point and direction) and the shape.

```python
Shape.findIntersection(
point: cq.Vector, direction: cq.Vector
) -> list[tuple[cq.Vector, cq.Vector]]
```

#### Project Text on Shape
Create 2D/3D text with a baseline following the given path on Shape as follows:
![projectText](doc/projectText.png)

```python
Shape.projectText(
txt: str,
fontsize: float,
depth: float,
path: Union[cq.Wire, cq.Edge],
font: str = "Arial",
fontPath: Optional[str] = None,
kind: Literal["regular", "bold", "italic"] = "regular",
valign: Literal["center", "top", "bottom"] = "center",
start: float = 0,
) -> cq.Compound:
```
The `start` parameter normally ranges between 0.0 and 1.0 and represents how far along the path the text will start. If `depth` is zero, Faces will be returned instead of Solids.

#### Emboss Text on Shape
Create 3D text with a baseline following the given path on Shape as follows:
![embossText](doc/embossText.png)

```python
Shape.embossText(
txt: str,
fontsize: float,
depth: float,
path: Union[cq.Wire, cq.Edge],
font: str = "Arial",
fontPath: Optional[str] = None,
kind: Literal["regular", "bold", "italic"] = "regular",
valign: Literal["center", "top", "bottom"] = "center",
start: float = 0,
) -> cq.Compound:
```
The `start` parameter normally ranges between 0.0 and 1.0 and represents how far along the path the text will start. If `depth` is zero, Faces will be returned instead of Solids.
Binary file added doc/conicalProjection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/embossFeature.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/embossText.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/embossWire.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/flatProjection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/projectText.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/textOnPath.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/thickenFace.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d63fbc3

Please sign in to comment.