bspy 4.4.1__py3-none-any.whl → 5.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -229,7 +229,7 @@ def normal(self, uvw, normalize=True, indices=None):
229
229
  nDep = self.nDep
230
230
 
231
231
  # Compute the normal using cofactors (determinants of subsets of the tangent space).
232
- sign = -1 if hasattr(self, "metadata") and self.metadata.get("flipNormal", False) else 1
232
+ sign = -1 if hasattr(self, "metadata") and self.metadata.get("negateNormal", False) else 1
233
233
  dtype = self.coefs.dtype if hasattr(self, "coefs") else self.coefsDtype
234
234
  if indices is None:
235
235
  indices = range(nDep)
@@ -435,7 +435,7 @@ def zeros_using_projected_polyhedron(self, epsilon=None, initialScale=None):
435
435
  return roots
436
436
 
437
437
  def _turning_point_determinant(self, uvw, cosTheta, sinTheta):
438
- sign = -1 if hasattr(self, "metadata") and self.metadata.get("flipNormal", False) else 1
438
+ sign = -1 if hasattr(self, "metadata") and self.metadata.get("negateNormal", False) else 1
439
439
  tangentSpace = self.jacobian(uvw).T
440
440
  return cosTheta * sign * np.linalg.det(tangentSpace[[j for j in range(self.nInd) if j != 0]]) - \
441
441
  sinTheta * sign * np.linalg.det(tangentSpace[[j for j in range(self.nInd) if j != 1]])
@@ -444,7 +444,7 @@ def _turning_point_determinant_gradient(self, uvw, cosTheta, sinTheta):
444
444
  dtype = self.coefs.dtype if hasattr(self, "coefs") else self.coefsDtype
445
445
  gradient = np.zeros(self.nInd, dtype)
446
446
 
447
- sign = -1 if hasattr(self, "metadata") and self.metadata.get("flipNormal", False) else 1
447
+ sign = -1 if hasattr(self, "metadata") and self.metadata.get("negateNormal", False) else 1
448
448
  tangentSpace = self.jacobian(uvw).T
449
449
  dTangentSpace = tangentSpace.copy()
450
450
 
@@ -698,7 +698,7 @@ def _contours_of_C1_spline_block(self, epsilon, evaluationEpsilon):
698
698
 
699
699
  # Extra step not in paper.
700
700
  # Run a checksum on the points, ensuring starting and ending points balance.
701
- # Start by flipping endpoints as needed, since we can miss turning points near endpoints.
701
+ # Start by negating endpoints as needed, since we can miss turning points near endpoints.
702
702
  if points[0].det < 0.0:
703
703
  point = points[0]
704
704
  points[0] = Point(point.d, -point.det, point.onUVBoundary, point.turningPoint, point.uvw)
@@ -973,19 +973,19 @@ def intersect(self, other):
973
973
  intersections.append(Manifold.Crossing(Hyperplane(1.0, zero[1] + epsilon, 0.0), Hyperplane(1.0, planeBounds[1], 0.0)))
974
974
 
975
975
  # Now, create the coincidence.
976
- left = Solid(1, False)
977
- left.add_boundary(Boundary(Hyperplane(-1.0, zero[0], 0.0), Solid(0, True)))
978
- left.add_boundary(Boundary(Hyperplane(1.0, zero[1], 0.0), Solid(0, True)))
979
- right = Solid(1, False)
976
+ firstPart = Solid(1, False)
977
+ firstPart.add_boundary(Boundary(Hyperplane(-1.0, zero[0], 0.0), Solid(0, True)))
978
+ firstPart.add_boundary(Boundary(Hyperplane(1.0, zero[1], 0.0), Solid(0, True)))
979
+ secondPart = Solid(1, False)
980
980
  if planeBounds[0] > planeBounds[1]:
981
981
  planeBounds = (planeBounds[1], planeBounds[0])
982
- right.add_boundary(Boundary(Hyperplane(-1.0, planeBounds[0], 0.0), Solid(0, True)))
983
- right.add_boundary(Boundary(Hyperplane(1.0, planeBounds[1], 0.0), Solid(0, True)))
982
+ secondPart.add_boundary(Boundary(Hyperplane(-1.0, planeBounds[0], 0.0), Solid(0, True)))
983
+ secondPart.add_boundary(Boundary(Hyperplane(1.0, planeBounds[1], 0.0), Solid(0, True)))
984
984
  alignment = np.dot(self.normal((zero[0],)), other._normal) # Use the first zero, since B-splines are closed on the left
985
985
  width = zero[1] - zero[0]
986
986
  transform = (planeBounds[1] - planeBounds[0]) / width
987
987
  translation = (planeBounds[0] * zero[1] - planeBounds[1] * zero[0]) / width
988
- intersections.append(Manifold.Coincidence(left, right, alignment, np.atleast_2d(transform), np.atleast_2d(1.0 / transform), np.atleast_1d(translation)))
988
+ intersections.append(Manifold.Coincidence(firstPart, secondPart, alignment, np.atleast_2d(transform), np.atleast_2d(1.0 / transform), np.atleast_1d(translation)))
989
989
  else:
990
990
  # Intersection is a point, so create a Manifold.Crossing.
991
991
  intersections.append(Manifold.Crossing(Hyperplane(1.0, zero, 0.0), Hyperplane(1.0, projection @ (self((zero,)) - other._point), 0.0)))
@@ -996,16 +996,16 @@ def intersect(self, other):
996
996
  contours = spline.contours()
997
997
  # Convert each contour into a Manifold.Crossing.
998
998
  for contour in contours:
999
- # The left portion is the contour returned for the spline-plane intersection.
1000
- left = contour
1001
- # The right portion is the contour projected onto the plane's domain, which we compute with samples and a least squares fit.
999
+ # The firstPart portion is the contour returned for the spline-plane intersection.
1000
+ firstPart = contour
1001
+ # The secondPart portion is the contour projected onto the plane's domain, which we compute with samples and a least squares fit.
1002
1002
  tValues = np.linspace(0.0, 1.0, contour.nCoef[0] + 5) # Over-sample a bit to reduce the condition number and avoid singular matrix
1003
1003
  points = []
1004
1004
  for t in tValues:
1005
1005
  zero = contour((t,))
1006
1006
  points.append(projection @ (self(zero) - other._point))
1007
- right = bspy.Spline.least_squares(tValues, np.array(points).T, contour.order, contour.knots)
1008
- intersections.append(Manifold.Crossing(left, right))
1007
+ secondPart = bspy.Spline.least_squares(tValues, np.array(points).T, contour.order, contour.knots)
1008
+ intersections.append(Manifold.Crossing(firstPart, secondPart))
1009
1009
  else:
1010
1010
  return NotImplemented
1011
1011
 
@@ -1040,17 +1040,17 @@ def intersect(self, other):
1040
1040
  intersections.append(Manifold.Crossing(Hyperplane(1.0, zero[1][0], 0.0), Hyperplane(1.0, zero[1][1] + epsilon, 0.0)))
1041
1041
 
1042
1042
  # Now, create the coincidence.
1043
- left = Solid(self.nInd, False)
1044
- left.add_boundary(Boundary(Hyperplane(-1.0, zero[0][0], 0.0), Solid(0, True)))
1045
- left.add_boundary(Boundary(Hyperplane(1.0, zero[1][0], 0.0), Solid(0, True)))
1046
- right = Solid(other.nInd, False)
1047
- right.add_boundary(Boundary(Hyperplane(-1.0, zero[0][1], 0.0), Solid(0, True)))
1048
- right.add_boundary(Boundary(Hyperplane(1.0, zero[1][1], 0.0), Solid(0, True)))
1043
+ firstPart = Solid(self.nInd, False)
1044
+ firstPart.add_boundary(Boundary(Hyperplane(-1.0, zero[0][0], 0.0), Solid(0, True)))
1045
+ firstPart.add_boundary(Boundary(Hyperplane(1.0, zero[1][0], 0.0), Solid(0, True)))
1046
+ secondPart = Solid(other.nInd, False)
1047
+ secondPart.add_boundary(Boundary(Hyperplane(-1.0, zero[0][1], 0.0), Solid(0, True)))
1048
+ secondPart.add_boundary(Boundary(Hyperplane(1.0, zero[1][1], 0.0), Solid(0, True)))
1049
1049
  alignment = np.dot(self.normal(zero[0][0]), other.normal(zero[0][1])) # Use the first zeros, since B-splines are closed on the left
1050
1050
  width = zero[1][0] - zero[0][0]
1051
1051
  transform = (zero[1][1] - zero[0][1]) / width
1052
1052
  translation = (zero[0][1] * zero[1][0] - zero[1][1] * zero[0][0]) / width
1053
- intersections.append(Manifold.Coincidence(left, right, alignment, np.atleast_2d(transform), np.atleast_2d(1.0 / transform), np.atleast_1d(translation)))
1053
+ intersections.append(Manifold.Coincidence(firstPart, secondPart, alignment, np.atleast_2d(transform), np.atleast_2d(1.0 / transform), np.atleast_1d(translation)))
1054
1054
  else:
1055
1055
  # Intersection is a point, so create a Manifold.Crossing.
1056
1056
  intersections.append(Manifold.Crossing(Hyperplane(1.0, zero[:self.nInd], 0.0), Hyperplane(1.0, zero[self.nInd:], 0.0)))
@@ -1073,16 +1073,16 @@ def intersect(self, other):
1073
1073
  contours = block.contours()
1074
1074
  # Convert each contour into a Manifold.Crossing, swapping the manifolds back.
1075
1075
  for contour in contours:
1076
- # Swap left and right, compared to not swapped.
1077
- left = bspy.Spline(contour.nInd, self.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[other.nInd:], contour.metadata)
1078
- right = bspy.Spline(contour.nInd, other.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[:other.nInd], contour.metadata)
1079
- intersections.append(Manifold.Crossing(left, right))
1076
+ # Swap firstPart and secondPart, compared to not swapped.
1077
+ firstPart = bspy.Spline(contour.nInd, self.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[other.nInd:], contour.metadata)
1078
+ secondPart = bspy.Spline(contour.nInd, other.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[:other.nInd], contour.metadata)
1079
+ intersections.append(Manifold.Crossing(firstPart, secondPart))
1080
1080
  else:
1081
1081
  # Convert each contour into a Manifold.Crossing.
1082
1082
  for contour in contours:
1083
- left = bspy.Spline(contour.nInd, self.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[:self.nInd], contour.metadata)
1084
- right = bspy.Spline(contour.nInd, other.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[self.nInd:], contour.metadata)
1085
- intersections.append(Manifold.Crossing(left, right))
1083
+ firstPart = bspy.Spline(contour.nInd, self.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[:self.nInd], contour.metadata)
1084
+ secondPart = bspy.Spline(contour.nInd, other.nInd, contour.order, contour.nCoef, contour.knots, contour.coefs[self.nInd:], contour.metadata)
1085
+ intersections.append(Manifold.Crossing(firstPart, secondPart))
1086
1086
  else:
1087
1087
  return NotImplemented
1088
1088
  else:
@@ -1091,55 +1091,55 @@ def intersect(self, other):
1091
1091
  # If self and other have normals, ensure they are pointing in the correct direction.
1092
1092
  if self.nInd + 1 == self.nDep and other.domain_dimension() + 1 == self.nDep:
1093
1093
  # Ensure the normals point outwards for both Manifolds in each crossing intersection.
1094
- # Note that evaluating left and right at 0.5 is always valid because either they are points or curves with [0.0, 1.0] domains.
1094
+ # Note that evaluating firstPart and secondPart at 0.5 is always valid because either they are points or curves with [0.0, 1.0] domains.
1095
1095
  domainPoint = np.atleast_1d(0.5)
1096
1096
  for i, intersection in enumerate(intersections):
1097
1097
  if isinstance(intersection, Manifold.Crossing):
1098
- left = intersection.left
1099
- right = intersection.right
1100
- if np.dot(self.tangent_space(left.evaluate(domainPoint)) @ left.normal(domainPoint), other.normal(right.evaluate(domainPoint))) < 0.0:
1101
- left = left.flip_normal()
1102
- if np.dot(other.tangent_space(right.evaluate(domainPoint)) @ right.normal(domainPoint), self.normal(left.evaluate(domainPoint))) < 0.0:
1103
- right = right.flip_normal()
1104
- intersections[i] = Manifold.Crossing(left, right)
1098
+ firstPart = intersection.firstPart
1099
+ secondPart = intersection.secondPart
1100
+ if np.dot(self.tangent_space(firstPart.evaluate(domainPoint)) @ firstPart.normal(domainPoint), other.normal(secondPart.evaluate(domainPoint))) < 0.0:
1101
+ firstPart = firstPart.negate_normal()
1102
+ if np.dot(other.tangent_space(secondPart.evaluate(domainPoint)) @ secondPart.normal(domainPoint), self.normal(firstPart.evaluate(domainPoint))) < 0.0:
1103
+ secondPart = secondPart.negate_normal()
1104
+ intersections[i] = Manifold.Crossing(firstPart, secondPart)
1105
1105
 
1106
1106
  return intersections
1107
1107
 
1108
- def complete_slice(self, slice, solid):
1108
+ def complete_cutout(self, cutout, solid):
1109
1109
  # Spline manifold domains have finite bounds.
1110
- slice.containsInfinity = False
1110
+ cutout.containsInfinity = False
1111
1111
  bounds = self.domain()
1112
1112
 
1113
1113
  # If manifold (self) has no intersections with solid, just check containment.
1114
- if not slice.boundaries:
1115
- if slice.dimension == 2:
1114
+ if not cutout.boundaries:
1115
+ if cutout.dimension == 2:
1116
1116
  if "Name" in self.metadata:
1117
1117
  logging.info(f"check containment:{self.metadata['Name']}")
1118
1118
  domain = bounds.T
1119
1119
  if solid.contains_point(self(0.5 * (domain[0] + domain[1]))):
1120
1120
  for boundary in Hyperplane.create_hypercube(bounds).boundaries:
1121
- slice.add_boundary(boundary)
1121
+ cutout.add_boundary(boundary)
1122
1122
  return
1123
1123
 
1124
1124
  # For curves, add domain bounds as needed.
1125
- if slice.dimension == 1:
1126
- slice.boundaries.sort(key=lambda b: (b.manifold.evaluate(0.0), b.manifold.normal(0.0)))
1125
+ if cutout.dimension == 1:
1126
+ cutout.boundaries.sort(key=lambda b: (b.manifold.evaluate(0.0), b.manifold.normal(0.0)))
1127
1127
  # First, check right end since we add new boundary to the end.
1128
- if abs(slice.boundaries[-1].manifold._point - bounds[0][1]) >= Manifold.minSeparation and \
1129
- slice.boundaries[-1].manifold._normal < 0.0:
1130
- slice.add_boundary(Boundary(Hyperplane(-slice.boundaries[-1].manifold._normal, bounds[0][1], 0.0), Solid(0, True)))
1128
+ if abs(cutout.boundaries[-1].manifold._point - bounds[0][1]) >= Manifold.minSeparation and \
1129
+ cutout.boundaries[-1].manifold._normal < 0.0:
1130
+ cutout.add_boundary(Boundary(Hyperplane(-cutout.boundaries[-1].manifold._normal, bounds[0][1], 0.0), Solid(0, True)))
1131
1131
  # Next, check left end since it's still untouched.
1132
- if abs(slice.boundaries[0].manifold._point - bounds[0][0]) >= Manifold.minSeparation and \
1133
- slice.boundaries[0].manifold._normal > 0.0:
1134
- slice.add_boundary(Boundary(Hyperplane(-slice.boundaries[0].manifold._normal, bounds[0][0], 0.0), Solid(0, True)))
1132
+ if abs(cutout.boundaries[0].manifold._point - bounds[0][0]) >= Manifold.minSeparation and \
1133
+ cutout.boundaries[0].manifold._normal > 0.0:
1134
+ cutout.add_boundary(Boundary(Hyperplane(-cutout.boundaries[0].manifold._normal, bounds[0][0], 0.0), Solid(0, True)))
1135
1135
 
1136
- # For surfaces, intersect full spline domain with existing slice boundaries.
1137
- if slice.dimension == 2:
1136
+ # For surfaces, intersect full spline domain with existing cutout boundaries.
1137
+ if cutout.dimension == 2:
1138
1138
  fullDomain = Hyperplane.create_hypercube(bounds)
1139
1139
  for newBoundary in fullDomain.boundaries: # Mark full domain boundaries as untouched
1140
1140
  newBoundary.touched = False
1141
1141
 
1142
- # Define function for adding slice points to full domain boundaries.
1142
+ # Define function for adding cutout points to full domain boundaries.
1143
1143
  def process_domain_point(boundary, domainPoint, adjustment):
1144
1144
  point = boundary.manifold.evaluate(domainPoint)
1145
1145
  # See if and where point touches full domain.
@@ -1148,24 +1148,24 @@ def complete_slice(self, slice, solid):
1148
1148
  if abs(np.dot(newBoundary.manifold._normal, vector)) < Manifold.minSeparation:
1149
1149
  # Add the point onto the new boundary (adjust normal evaluation point to move away from boundary).
1150
1150
  normal = np.sign(newBoundary.manifold._tangentSpace.T @ boundary.manifold.normal(domainPoint + adjustment))
1151
- newBoundary.domain.add_boundary(Boundary(Hyperplane(normal, newBoundary.manifold._tangentSpace.T @ vector, 0.0), Solid(0, True)))
1151
+ newBoundary.trim.add_boundary(Boundary(Hyperplane(normal, newBoundary.manifold._tangentSpace.T @ vector, 0.0), Solid(0, True)))
1152
1152
  newBoundary.touched = True
1153
1153
  break
1154
1154
 
1155
1155
  # Go through existing boundaries and check if either of their endpoints lies on the spline's bounds.
1156
- for boundary in slice.boundaries:
1157
- domainBoundaries = boundary.domain.boundaries
1156
+ for boundary in cutout.boundaries:
1157
+ domainBoundaries = boundary.trim.boundaries
1158
1158
  domainBoundaries.sort(key=lambda boundary: (boundary.manifold.evaluate(0.0), boundary.manifold.normal(0.0)))
1159
1159
  process_domain_point(boundary, domainBoundaries[0].manifold._point, Manifold.minSeparation)
1160
1160
  if len(domainBoundaries) > 1:
1161
1161
  process_domain_point(boundary, domainBoundaries[-1].manifold._point, -Manifold.minSeparation)
1162
1162
 
1163
- # For touched boundaries, remove domain bounds that aren't needed and then add boundary to slice.
1163
+ # For touched boundaries, remove domain bounds that aren't needed and then add boundary to cutout.
1164
1164
  boundaryWasTouched = False
1165
1165
  for newBoundary in fullDomain.boundaries:
1166
1166
  if newBoundary.touched:
1167
1167
  boundaryWasTouched = True
1168
- domainBoundaries = newBoundary.domain.boundaries
1168
+ domainBoundaries = newBoundary.trim.boundaries
1169
1169
  domainBoundaries.sort(key=lambda boundary: (boundary.manifold.evaluate(0.0), boundary.manifold.normal(0.0)))
1170
1170
  # Ensure domain endpoints don't overlap and their normals are consistent.
1171
1171
  if abs(domainBoundaries[0].manifold._point - domainBoundaries[1].manifold._point) < Manifold.minSeparation or \
@@ -1174,10 +1174,10 @@ def complete_slice(self, slice, solid):
1174
1174
  if abs(domainBoundaries[-1].manifold._point - domainBoundaries[-2].manifold._point) < Manifold.minSeparation or \
1175
1175
  domainBoundaries[-2].manifold._normal > 0.0:
1176
1176
  del domainBoundaries[-1]
1177
- slice.add_boundary(newBoundary)
1177
+ cutout.add_boundary(newBoundary)
1178
1178
 
1179
1179
  if boundaryWasTouched:
1180
- # Touch untouched boundaries that are connected to touched boundary endpoints and add them to slice.
1180
+ # Touch untouched boundaries that are connected to touched boundary endpoints and add them to cutout.
1181
1181
  boundaryMap = ((2, 3, 0), (2, 3, -1), (0, 1, 0), (0, 1, -1)) # Map of which full domain boundaries touch each other
1182
1182
  while True:
1183
1183
  noTouches = True
@@ -1185,21 +1185,21 @@ def complete_slice(self, slice, solid):
1185
1185
  if not newBoundary.touched:
1186
1186
  leftBoundary = fullDomain.boundaries[map[0]]
1187
1187
  rightBoundary = fullDomain.boundaries[map[1]]
1188
- if leftBoundary.touched and abs(leftBoundary.domain.boundaries[map[2]].manifold._point - bound) < Manifold.minSeparation:
1188
+ if leftBoundary.touched and abs(leftBoundary.trim.boundaries[map[2]].manifold._point - bound) < Manifold.minSeparation:
1189
1189
  newBoundary.touched = True
1190
- slice.add_boundary(newBoundary)
1190
+ cutout.add_boundary(newBoundary)
1191
1191
  noTouches = False
1192
- elif rightBoundary.touched and abs(rightBoundary.domain.boundaries[map[2]].manifold._point - bound) < Manifold.minSeparation:
1192
+ elif rightBoundary.touched and abs(rightBoundary.trim.boundaries[map[2]].manifold._point - bound) < Manifold.minSeparation:
1193
1193
  newBoundary.touched = True
1194
- slice.add_boundary(newBoundary)
1194
+ cutout.add_boundary(newBoundary)
1195
1195
  noTouches = False
1196
1196
  if noTouches:
1197
1197
  break
1198
1198
  else:
1199
- # No slice boundaries touched the full domain (a hole), so only add full domain if it is contained in the solid.
1199
+ # No cutout boundaries touched the full domain (a hole), so only add full domain if it is contained in the solid.
1200
1200
  if solid.contains_point(self.evaluate(bounds[:,0])):
1201
1201
  for newBoundary in fullDomain.boundaries:
1202
- slice.add_boundary(newBoundary)
1202
+ cutout.add_boundary(newBoundary)
1203
1203
 
1204
1204
  def full_domain(self):
1205
1205
  return Hyperplane.create_hypercube(self.domain())
bspy/_spline_milling.py CHANGED
@@ -254,10 +254,10 @@ def offset(self, edgeRadius, bitRadius=None, angle=np.pi / 2.2, path=None, subtr
254
254
  tangent = self.jacobian(path(knot)) @ path.derivative((1,), knot)
255
255
  else:
256
256
  tangent = self.derivative((1,), knot)
257
- flipped = np.dot(tangent, offset.derivative((1,), knot)) < 0
258
- if flipped and start is None:
257
+ negated = np.dot(tangent, offset.derivative((1,), knot)) < 0
258
+ if negated and start is None:
259
259
  start = knot
260
- if not flipped and start is not None:
260
+ if not negated and start is not None:
261
261
  cusps.append((start, previousKnot))
262
262
  start = None
263
263
  previousKnot = knot
bspy/hyperplane.py CHANGED
@@ -41,19 +41,19 @@ class Hyperplane(Manifold):
41
41
  def __repr__(self):
42
42
  return "Hyperplane({0}, {1}, {2})".format(self._normal, self._point, self._tangentSpace)
43
43
 
44
- def complete_slice(self, slice, solid):
44
+ def complete_cutout(self, cutout, solid):
45
45
  """
46
- Add any missing inherent (implicit) boundaries of this manifold's domain to the given slice of the
47
- given solid that are needed to make the slice valid and complete.
46
+ Add any missing inherent (implicit) boundaries of this manifold's domain to the given cutout of the
47
+ given solid that are needed to make the cutout valid and complete.
48
48
 
49
49
  Parameters
50
50
  ----------
51
- slice : `Solid`
52
- The slice of the given solid formed by the manifold. The slice may be incomplete, missing some of the
51
+ cutout : `Solid`
52
+ The cutout of the given solid formed by the manifold. The cutout may be incomplete, missing some of the
53
53
  manifold's inherent domain boundaries. Its dimension must match `self.domain_dimension()`.
54
54
 
55
55
  solid : `Solid`
56
- The solid being sliced by the manifold. Its dimension must match `self.range_dimension()`.
56
+ The solid determining the cutout of the manifold. Its dimension must match `self.range_dimension()`.
57
57
 
58
58
  Parameters
59
59
  ----------
@@ -63,17 +63,17 @@ class Hyperplane(Manifold):
63
63
 
64
64
  See Also
65
65
  --------
66
- `Solid.slice` : Slice the solid by a manifold.
66
+ `Solid.compute_cutout` : Compute the cutout portion of the manifold within the solid.
67
67
 
68
68
  Notes
69
69
  -----
70
70
  Since hyperplanes have no inherent domain boundaries, this operation only tests for
71
71
  point containment for zero-dimension hyperplanes (points).
72
72
  """
73
- assert self.domain_dimension() == slice.dimension
73
+ assert self.domain_dimension() == cutout.dimension
74
74
  assert self.range_dimension() == solid.dimension
75
- if slice.dimension == 0:
76
- slice.containsInfinity = solid.contains_point(self._point)
75
+ if cutout.dimension == 0:
76
+ cutout.containsInfinity = solid.contains_point(self._point)
77
77
 
78
78
  def copy(self):
79
79
  """
@@ -86,7 +86,7 @@ class Hyperplane(Manifold):
86
86
  return Hyperplane(self._normal, self._point, self._tangentSpace)
87
87
 
88
88
  @staticmethod
89
- def create_axis_aligned(dimension, axis, offset, flipNormal=False):
89
+ def create_axis_aligned(dimension, axis, offset, negateNormal=False):
90
90
  """
91
91
  Create an axis-aligned hyperplane.
92
92
 
@@ -101,7 +101,7 @@ class Hyperplane(Manifold):
101
101
  offset : `float`
102
102
  The offset from zero along the axis of a point on the hyperplane.
103
103
 
104
- flipNormal : `bool`, optional
104
+ negateNormal : `bool`, optional
105
105
  A Boolean indicating that the normal should point toward in the negative direction along the axis.
106
106
  Default is False, meaning the normal points in the positive direction along the axis.
107
107
 
@@ -112,7 +112,7 @@ class Hyperplane(Manifold):
112
112
  """
113
113
  assert dimension > 0
114
114
  diagonal = np.identity(dimension)
115
- sign = -1.0 if flipNormal else 1.0
115
+ sign = -1.0 if negateNormal else 1.0
116
116
  normal = sign * diagonal[:,axis]
117
117
  point = offset * normal
118
118
  if dimension > 1:
@@ -178,21 +178,6 @@ class Hyperplane(Manifold):
178
178
  """
179
179
  return np.dot(self._tangentSpace, np.atleast_1d(domainPoint)) + self._point
180
180
 
181
- def flip_normal(self):
182
- """
183
- Flip the direction of the normal.
184
-
185
- Returns
186
- -------
187
- hyperplane : `Hyperplane`
188
- The hyperplane with flipped normal. The hyperplane retains the same tangent space.
189
-
190
- See Also
191
- --------
192
- `Solid.complement` : Return the complement of the solid: whatever was inside is outside and vice-versa.
193
- """
194
- return Hyperplane(-self._normal, self._point, self._tangentSpace)
195
-
196
181
  @staticmethod
197
182
  def from_dict(dictionary):
198
183
  """
@@ -244,14 +229,14 @@ class Hyperplane(Manifold):
244
229
  (Hyperplanes will have at most one intersection, but other types of manifolds can have several.)
245
230
  Each intersection records either a crossing or a coincident region.
246
231
 
247
- For a crossing, intersection is a `Manifold.Crossing`: (left, right)
248
- * left : `Manifold` in the manifold's domain where the manifold and the other cross.
249
- * right : `Manifold` in the other's domain where the manifold and the other cross.
232
+ For a crossing, intersection is a `Manifold.Crossing`: (firstPart, secondPart)
233
+ * firstPart : `Manifold` in the manifold's domain where the manifold and the other cross.
234
+ * secondPart : `Manifold` in the other's domain where the manifold and the other cross.
250
235
  * Both intersection manifolds have the same domain and range (the crossing between the manifold and the other).
251
236
 
252
- For a coincident region, intersection is a `Manifold.Coincidence`: (left, right, alignment, transform, inverse, translation)
253
- * left : `Solid` in the manifold's domain within which the manifold and the other are coincident.
254
- * right : `Solid` in the other's domain within which the manifold and the other are coincident.
237
+ For a coincident region, intersection is a `Manifold.Coincidence`: (firstPart, secondPart, alignment, transform, inverse, translation)
238
+ * firstPart : `Solid` in the manifold's domain within which the manifold and the other are coincident.
239
+ * secondPart : `Solid` in the other's domain within which the manifold and the other are coincident.
255
240
  * alignment : scalar value holding the normal alignment between the manifold and the other (the dot product of their unit normals).
256
241
  * transform : `numpy.array` holding the transform matrix from the manifold's domain to the other's domain.
257
242
  * inverse : `numpy.array` holding the inverse transform matrix from the other's domain to the boundary's domain.
@@ -260,7 +245,7 @@ class Hyperplane(Manifold):
260
245
 
261
246
  See Also
262
247
  --------
263
- `Solid.slice` : slice the solid by a manifold.
248
+ `Solid.compute_cutout` : Compute the cutout portion of the manifold within the solid.
264
249
  `numpy.linalg.svd` : Compute the singular value decomposition of a matrix array.
265
250
 
266
251
  Notes
@@ -361,6 +346,21 @@ class Hyperplane(Manifold):
361
346
 
362
347
  return intersections
363
348
 
349
+ def negate_normal(self):
350
+ """
351
+ Negate the direction of the normal.
352
+
353
+ Returns
354
+ -------
355
+ hyperplane : `Hyperplane`
356
+ The hyperplane with negated normal. The hyperplane retains the same tangent space.
357
+
358
+ See Also
359
+ --------
360
+ `Solid.complement` : Return the complement of the solid: whatever was inside is outside and vice-versa.
361
+ """
362
+ return Hyperplane(-self._normal, self._point, self._tangentSpace)
363
+
364
364
  def normal(self, domainPoint, normalize=True, indices=None):
365
365
  """
366
366
  Return the normal.
bspy/manifold.py CHANGED
@@ -15,8 +15,8 @@ class Manifold:
15
15
  minSeparation = 0.0001
16
16
  """If two points are within minSeparation of each each other, they are coincident."""
17
17
 
18
- Crossing = namedtuple('Crossing', ('left','right'))
19
- Coincidence = namedtuple('Coincidence', ('left', 'right', 'alignment', 'transform', 'inverse', 'translation'))
18
+ Crossing = namedtuple('Crossing', ('firstPart','secondPart'))
19
+ Coincidence = namedtuple('Coincidence', ('firstPart', 'secondPart', 'alignment', 'transform', 'inverse', 'translation'))
20
20
  """Return type for intersect."""
21
21
 
22
22
  factory = {}
@@ -43,14 +43,14 @@ class Manifold:
43
43
  A list of intersections between the two manifolds.
44
44
  Each intersection records either a crossing or a coincident region.
45
45
 
46
- For a crossing, intersection is a Manifold.Crossing: (left, right)
47
- * left : `Manifold` in the manifold's domain where the manifold and the other cross.
48
- * right : `Manifold` in the other's domain where the manifold and the other cross.
46
+ For a crossing, intersection is a Manifold.Crossing: (firstPart, secondPart)
47
+ * firstPart : `Manifold` in the manifold's domain where the manifold and the other cross.
48
+ * secondPart : `Manifold` in the other's domain where the manifold and the other cross.
49
49
  * Both intersection manifolds have the same domain and range (the crossing between the manifold and the other).
50
50
 
51
- For a coincident region, intersection is Manifold.Coincidence: (left, right, alignment, transform, inverse, translation)
52
- * left : `Solid` in the manifold's domain within which the manifold and the other are coincident.
53
- * right : `Solid` in the other's domain within which the manifold and the other are coincident.
51
+ For a coincident region, intersection is Manifold.Coincidence: (firstPart, secondPart, alignment, transform, inverse, translation)
52
+ * firstPart : `Solid` in the manifold's domain within which the manifold and the other are coincident.
53
+ * secondPart : `Solid` in the other's domain within which the manifold and the other are coincident.
54
54
  * alignment : scalar value holding the normal alignment between the manifold and the other (the dot product of their unit normals).
55
55
  * transform : `numpy.array` holding the matrix transform from the boundary's domain to the other's domain.
56
56
  * inverse : `numpy.array` holding the matrix inverse transform from the other's domain to the boundary's domain.
@@ -63,7 +63,7 @@ class Manifold:
63
63
  See Also
64
64
  --------
65
65
  `intersect` : Intersect two manifolds.
66
- `Solid.slice` : slice the solid by a manifold.
66
+ `Solid.compute_cutout` : Compute the cutout portion of the manifold within the solid.
67
67
 
68
68
  Notes
69
69
  -----
@@ -97,31 +97,31 @@ class Manifold:
97
97
 
98
98
  return intersections, isTwin
99
99
 
100
- def complete_slice(self, slice, solid):
100
+ def complete_cutout(self, cutout, solid):
101
101
  """
102
- Add any missing inherent (implicit) boundaries of this manifold's domain to the given slice of the
103
- given solid that are needed to make the slice valid and complete.
102
+ Add any missing inherent (implicit) boundaries of this manifold's domain to the given cutout of the
103
+ given solid that are needed to make the cutout valid and complete.
104
104
 
105
105
  Parameters
106
106
  ----------
107
- slice : `Solid`
108
- The slice of the given solid formed by the manifold. The slice may be incomplete, missing some of the
107
+ cutout : `Solid`
108
+ The cutout of the given solid formed by the manifold. The cutout may be incomplete, missing some of the
109
109
  manifold's inherent domain boundaries. Its dimension must match `self.domain_dimension()`.
110
110
 
111
111
  solid : `Solid`
112
- The solid being sliced by the manifold. Its dimension must match `self.range_dimension()`.
112
+ The solid determining the cutout of the manifold. Its dimension must match `self.range_dimension()`.
113
113
 
114
114
  See Also
115
115
  --------
116
- `Solid.slice` : Slice the solid by a manifold.
116
+ `Solid.compute_cutout` : Compute the cutout portion of the manifold within the solid.
117
117
 
118
118
  Notes
119
119
  -----
120
120
  For manifolds without inherent domain boundaries (like hyperplanes), the operation does nothing.
121
121
  """
122
- assert self.domain_dimension() == slice.dimension
122
+ assert self.domain_dimension() == cutout.dimension
123
123
  assert self.range_dimension() == solid.dimension
124
-
124
+
125
125
  def copy(self):
126
126
  """
127
127
  Copy the manifold.
@@ -157,21 +157,6 @@ class Manifold:
157
157
  """
158
158
  return None
159
159
 
160
- def flip_normal(self):
161
- """
162
- Flip the direction of the normal.
163
-
164
- Returns
165
- -------
166
- manifold : `Manifold`
167
- The manifold with flipped normal. The manifold retains the same tangent space.
168
-
169
- See Also
170
- --------
171
- `Solid.complement` : Return the complement of the solid: whatever was inside is outside and vice-versa.
172
- """
173
- return None
174
-
175
160
  @staticmethod
176
161
  def from_dict(dictionary):
177
162
  """
@@ -222,14 +207,14 @@ class Manifold:
222
207
  A list of intersections between the two manifolds.
223
208
  Each intersection records either a crossing or a coincident region.
224
209
 
225
- For a crossing, intersection is a `Manifold.Crossing`: (left, right)
226
- * left : `Manifold` in the manifold's domain where the manifold and the other cross.
227
- * right : `Manifold` in the other's domain where the manifold and the other cross.
210
+ For a crossing, intersection is a `Manifold.Crossing`: (firstPart, secondPart)
211
+ * firstPart : `Manifold` in the manifold's domain where the manifold and the other cross.
212
+ * secondPart : `Manifold` in the other's domain where the manifold and the other cross.
228
213
  * Both intersection manifolds have the same domain and range (the crossing between the manifold and the other).
229
214
 
230
- For a coincident region, intersection is a `Manifold.Coincidence`: (left, right, alignment, transform, inverse, translation)
231
- * left : `Solid` in the manifold's domain within which the manifold and the other are coincident.
232
- * right : `Solid` in the other's domain within which the manifold and the other are coincident.
215
+ For a coincident region, intersection is a `Manifold.Coincidence`: (firstPart, secondPart, alignment, transform, inverse, translation)
216
+ * firstPart : `Solid` in the manifold's domain within which the manifold and the other are coincident.
217
+ * secondPart : `Solid` in the other's domain within which the manifold and the other are coincident.
233
218
  * alignment : scalar value holding the normal alignment between the manifold and the other (the dot product of their unit normals).
234
219
  * transform : `numpy.array` holding the transform matrix from the manifold's domain to the other's domain.
235
220
  * inverse : `numpy.array` holding the inverse transform matrix from the other's domain to the boundary's domain.
@@ -239,7 +224,7 @@ class Manifold:
239
224
  See Also
240
225
  --------
241
226
  `cached_intersect` : Intersect two manifolds, caching the result for twins (same intersection but swapping self and other).
242
- `Solid.slice` : slice the solid by a manifold.
227
+ `Solid.compute_cutout` : Compute the cutout portion of the manifold within the solid.
243
228
 
244
229
  Notes
245
230
  -----
@@ -247,6 +232,21 @@ class Manifold:
247
232
  """
248
233
  return NotImplemented
249
234
 
235
+ def negate_normal(self):
236
+ """
237
+ Negate the direction of the normal.
238
+
239
+ Returns
240
+ -------
241
+ manifold : `Manifold`
242
+ The manifold with negated normal. The manifold retains the same tangent space.
243
+
244
+ See Also
245
+ --------
246
+ `Solid.complement` : Return the complement of the solid: whatever was inside is outside and vice-versa.
247
+ """
248
+ return None
249
+
250
250
  def normal(self, domainPoint, normalize=True, indices=None):
251
251
  """
252
252
  Return the normal.