Add the option to use explicit x= or y= in path_to
This commit is contained in:
parent
d02ea400a0
commit
086d07a82d
@ -236,8 +236,10 @@ class Pather(Builder):
|
||||
self,
|
||||
portspec: str,
|
||||
ccw: SupportsBool | None,
|
||||
position: float,
|
||||
position: float | None = None,
|
||||
*,
|
||||
x: float | None = None,
|
||||
y: float | None = None,
|
||||
tool_port_names: tuple[str, str] = ('A', 'B'),
|
||||
base_name: str = '_pathto',
|
||||
**kwargs,
|
||||
@ -246,8 +248,13 @@ class Pather(Builder):
|
||||
logger.error('Skipping path_to() since device is dead')
|
||||
return self
|
||||
|
||||
pos_count = sum(vv is not None for vv in (position, x, y))
|
||||
if pos_count > 1:
|
||||
raise BuildError('Only one of `position`, `x`, and `y` may be specified at once')
|
||||
if pos_count < 1:
|
||||
raise BuildError('One of `position`, `x`, and `y` must be specified')
|
||||
|
||||
port = self.pattern[portspec]
|
||||
x, y = port.offset
|
||||
if port.rotation is None:
|
||||
raise PortError(f'Port {portspec} has no rotation and cannot be used for path_to()')
|
||||
|
||||
@ -256,13 +263,25 @@ class Pather(Builder):
|
||||
|
||||
is_horizontal = numpy.isclose(port.rotation % pi, 0)
|
||||
if is_horizontal:
|
||||
if numpy.sign(numpy.cos(port.rotation)) == numpy.sign(position - x):
|
||||
raise BuildError(f'path_to routing to behind source port: x={x:g} to {position:g}')
|
||||
length = numpy.abs(position - x)
|
||||
if y is not None:
|
||||
raise BuildError(f'Asked to path to y-coordinate, but port is horizontal')
|
||||
if position is None:
|
||||
position = x
|
||||
else:
|
||||
if numpy.sign(numpy.sin(port.rotation)) == numpy.sign(position - y):
|
||||
raise BuildError(f'path_to routing to behind source port: y={y:g} to {position:g}')
|
||||
length = numpy.abs(position - y)
|
||||
if x is not None:
|
||||
raise BuildError(f'Asked to path to x-coordinate, but port is vertical')
|
||||
if position is None:
|
||||
position = y
|
||||
|
||||
x0, y0 = port.offset
|
||||
if is_horizontal:
|
||||
if numpy.sign(numpy.cos(port.rotation)) == numpy.sign(position - x0):
|
||||
raise BuildError(f'path_to routing to behind source port: x0={x0:g} to {position:g}')
|
||||
length = numpy.abs(position - x0)
|
||||
else:
|
||||
if numpy.sign(numpy.sin(port.rotation)) == numpy.sign(position - y0):
|
||||
raise BuildError(f'path_to routing to behind source port: y0={y0:g} to {position:g}')
|
||||
length = numpy.abs(position - y0)
|
||||
|
||||
return self.path(portspec, ccw, length, tool_port_names=tool_port_names, base_name=base_name, **kwargs)
|
||||
|
||||
@ -286,7 +305,7 @@ class Pather(Builder):
|
||||
if 'bound_type' in kwargs:
|
||||
bound_types.add(kwargs['bound_type'])
|
||||
bound = kwargs['bound']
|
||||
for bt in ('emin', 'emax', 'pmin', 'pmax', 'min_past_furthest'):
|
||||
for bt in ('emin', 'emax', 'pmin', 'pmax', 'xmin', 'xmax', 'ymin', 'ymax', 'min_past_furthest'):
|
||||
if bt in kwargs:
|
||||
bound_types.add(bt)
|
||||
bound = kwargs[bt]
|
||||
|
@ -301,15 +301,23 @@ class RenderPather(PortList):
|
||||
self,
|
||||
portspec: str,
|
||||
ccw: SupportsBool | None,
|
||||
position: float,
|
||||
position: float | None = None,
|
||||
*,
|
||||
x: float | None = None,
|
||||
y: float | None = None,
|
||||
**kwargs,
|
||||
) -> Self:
|
||||
if self._dead:
|
||||
logger.error('Skipping path_to() since device is dead')
|
||||
return self
|
||||
|
||||
pos_count = sum(vv is not None for vv in (position, x, y))
|
||||
if pos_count > 1:
|
||||
raise BuildError('Only one of `position`, `x`, and `y` may be specified at once')
|
||||
if pos_count < 1:
|
||||
raise BuildError('One of `position`, `x`, and `y` must be specified')
|
||||
|
||||
port = self.pattern[portspec]
|
||||
x, y = port.offset
|
||||
if port.rotation is None:
|
||||
raise PortError(f'Port {portspec} has no rotation and cannot be used for path_to()')
|
||||
|
||||
@ -318,13 +326,25 @@ class RenderPather(PortList):
|
||||
|
||||
is_horizontal = numpy.isclose(port.rotation % pi, 0)
|
||||
if is_horizontal:
|
||||
if numpy.sign(numpy.cos(port.rotation)) == numpy.sign(position - x):
|
||||
raise BuildError(f'path_to routing to behind source port: x={x:g} to {position:g}')
|
||||
length = numpy.abs(position - x)
|
||||
if y is not None:
|
||||
raise BuildError(f'Asked to path to y-coordinate, but port is horizontal')
|
||||
if position is None:
|
||||
position = x
|
||||
else:
|
||||
if numpy.sign(numpy.sin(port.rotation)) == numpy.sign(position - y):
|
||||
raise BuildError(f'path_to routing to behind source port: y={y:g} to {position:g}')
|
||||
length = numpy.abs(position - y)
|
||||
if x is not None:
|
||||
raise BuildError(f'Asked to path to x-coordinate, but port is vertical')
|
||||
if position is None:
|
||||
position = y
|
||||
|
||||
x0, y0 = port.offset
|
||||
if is_horizontal:
|
||||
if numpy.sign(numpy.cos(port.rotation)) == numpy.sign(position - x0):
|
||||
raise BuildError(f'path_to routing to behind source port: x0={x0:g} to {position:g}')
|
||||
length = numpy.abs(position - x0)
|
||||
else:
|
||||
if numpy.sign(numpy.sin(port.rotation)) == numpy.sign(position - y0):
|
||||
raise BuildError(f'path_to routing to behind source port: y0={y0:g} to {position:g}')
|
||||
length = numpy.abs(position - y0)
|
||||
|
||||
return self.path(portspec, ccw, length, **kwargs)
|
||||
|
||||
@ -345,7 +365,7 @@ class RenderPather(PortList):
|
||||
if 'bound_type' in kwargs:
|
||||
bound_types.add(kwargs['bound_type'])
|
||||
bound = kwargs['bound']
|
||||
for bt in ('emin', 'emax', 'pmin', 'pmax', 'min_past_furthest'):
|
||||
for bt in ('emin', 'emax', 'pmin', 'pmax', 'xmin', 'xmax', 'ymin', 'ymax', 'min_past_furthest'):
|
||||
if bt in kwargs:
|
||||
bound_types.add(bt)
|
||||
bound = kwargs[bt]
|
||||
|
@ -53,9 +53,9 @@ def ell(
|
||||
The distance between furthest out-port (B) and the innermost bend (D's bend).
|
||||
- 'max_extension' or 'emax':
|
||||
The total extension value for the closest-in port (C in the diagram).
|
||||
- 'min_position' or 'pmin':
|
||||
- 'min_position', 'pmin', 'xmin', 'ymin':
|
||||
The coordinate of the innermost bend (D's bend).
|
||||
- 'max_position' or 'pmax':
|
||||
- 'max_position', 'pmax', 'xmax', 'ymax':
|
||||
The coordinate of the outermost bend (A's bend).
|
||||
|
||||
`bound` can also be a vector. If specifying an extension (e.g. 'min_extension',
|
||||
@ -109,6 +109,12 @@ def ell(
|
||||
raise BuildError('set_rotation must be specified if no ports have rotations!')
|
||||
rotations = numpy.full_like(has_rotation, set_rotation, dtype=float)
|
||||
|
||||
is_horizontal = numpy.isclose(rotations[0] % pi, 0)
|
||||
if bound_type in ('ymin', 'ymax') and is_horizontal:
|
||||
raise BuildError('Asked for {bound_type} position but ports are pointing along the x-axis!')
|
||||
elif bound_type in ('xmin', 'xmax') and not is_horizontal:
|
||||
raise BuildError('Asked for {bound_type} position but ports are pointing along the y-axis!')
|
||||
|
||||
direction = rotations[0] + pi # direction we want to travel in (+pi relative to port)
|
||||
rot_matrix = rotation_matrix_2d(-direction)
|
||||
|
||||
@ -184,9 +190,9 @@ def ell(
|
||||
rot_bound = -bound if neg else bound
|
||||
|
||||
min_possible = x_start + offsets
|
||||
if bound_type in ('pmax', 'max_position'):
|
||||
if bound_type in ('pmax', 'max_position', 'xmax', 'ymax'):
|
||||
extension = rot_bound - min_possible.max()
|
||||
elif bound_type in ('pmin', 'min_position'):
|
||||
elif bound_type in ('pmin', 'min_position', 'xmin', 'ymin'):
|
||||
extension = rot_bound - min_possible.min()
|
||||
|
||||
offsets += extension
|
||||
|
Loading…
Reference in New Issue
Block a user