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