141 lines
4.0 KiB
Python
141 lines
4.0 KiB
Python
import cadquery as cq
|
|
|
|
from cadquery.occ_impl.geom import Vector
|
|
from cadquery.occ_impl.shape_protocols import (
|
|
geom_LUT_EDGE,
|
|
geom_LUT_FACE,
|
|
)
|
|
|
|
from pyparsing import (
|
|
pyparsing_common,
|
|
Literal,
|
|
Word,
|
|
nums,
|
|
Optional,
|
|
Combine,
|
|
oneOf,
|
|
Group,
|
|
infixNotation,
|
|
opAssoc,
|
|
)
|
|
|
|
def _makeGrammar():
|
|
"""
|
|
Define the simple string selector grammar using PyParsing
|
|
"""
|
|
|
|
# float definition
|
|
point = Literal(".")
|
|
plusmin = Literal("+") | Literal("-")
|
|
number = Word(nums)
|
|
integer = Combine(Optional(plusmin) + number)
|
|
floatn = Combine(integer + Optional(point + Optional(number)))
|
|
|
|
# vector definition
|
|
lbracket = Literal("(")
|
|
rbracket = Literal(")")
|
|
comma = Literal(",")
|
|
vector = Combine(
|
|
lbracket + floatn("x") + comma + floatn("y") + comma + floatn("z") + rbracket,
|
|
adjacent=False,
|
|
)
|
|
|
|
# direction definition
|
|
simple_dir = oneOf(["X", "Y", "Z", "XY", "XZ", "YZ"] + ["x", "y", "z", "xy", "xz", "yz"])
|
|
direction = simple_dir("simple_dir") | vector("vector_dir")
|
|
|
|
# CQ type definition
|
|
cqtype = oneOf(
|
|
set(geom_LUT_EDGE.values()) | set(geom_LUT_FACE.values()), caseless=True,
|
|
)
|
|
cqtype = cqtype.setParseAction(pyparsing_common.upcaseTokens)
|
|
|
|
# type operator
|
|
type_op = Literal("%")
|
|
|
|
# direction operator
|
|
direction_op = oneOf([">", "<"])
|
|
|
|
# center Nth operator
|
|
center_nth_op = oneOf([">>", "<<"])
|
|
|
|
# index definition
|
|
ix_number = Group(Optional("-") + Word(nums))
|
|
lsqbracket = Literal("[").suppress()
|
|
rsqbracket = Literal("]").suppress()
|
|
|
|
index = lsqbracket + ix_number("index") + rsqbracket
|
|
|
|
# other operators
|
|
other_op = oneOf(["|", "#", "+", "-"])
|
|
|
|
# named view
|
|
named_view = oneOf(["front", "back", "left", "right", "top", "bottom"])
|
|
|
|
return (
|
|
direction("only_dir")
|
|
| (type_op("type_op") + cqtype("cq_type"))
|
|
| (direction_op("dir_op") + direction("dir") + Optional(index))
|
|
| (center_nth_op("center_nth_op") + direction("dir") + Optional(index))
|
|
| (other_op("other_op") + direction("dir"))
|
|
| named_view("named_view")
|
|
)
|
|
|
|
|
|
old_getVector = cq.selectors._SimpleStringSyntaxSelector._getVector
|
|
|
|
def _getVector(self, pr):
|
|
if "simple_dir" in pr and pr.simple_dir in cq.selectors._SimpleStringSyntaxSelector.local_axes:
|
|
return cq.selectors._SimpleStringSyntaxSelector.local_axes[pr.simple_dir]
|
|
else:
|
|
return old_getVector(self, pr)
|
|
|
|
class LocalCoordinates:
|
|
def __init__(self, plane):
|
|
self.plane = plane
|
|
self.old_axes = None
|
|
|
|
def __enter__(self):
|
|
self.old_axes, cq.selectors._SimpleStringSyntaxSelector.local_axes = (cq.selectors._SimpleStringSyntaxSelector.local_axes,
|
|
{
|
|
'x': self.plane.xDir,
|
|
'y': self.plane.yDir,
|
|
'z': self.plane.zDir,
|
|
'xy': self.plane.xDir + self.plane.yDir,
|
|
'yz': self.plane.yDir + self.plane.zDir,
|
|
'xz': self.plane.xDir + self.plane.zDir,
|
|
})
|
|
|
|
def __exit__(self, _exc_type, _exc_value, _traceback):
|
|
cq.selectors._SimpleStringSyntaxSelector.local_axes = self.old_axes
|
|
|
|
|
|
def _filter(self, objs, selector):
|
|
selectorObj: Selector
|
|
if selector:
|
|
if isinstance(selector, str):
|
|
with LocalCoordinates(self.plane):
|
|
selectorObj = cq.selectors.StringSyntaxSelector(selector)
|
|
else:
|
|
selectorObj = selector
|
|
toReturn = selectorObj.filter(objs)
|
|
else:
|
|
toReturn = objs
|
|
|
|
return toReturn
|
|
|
|
cq.selectors._SimpleStringSyntaxSelector.local_axes = {
|
|
"x": Vector(1, 0, 0),
|
|
"y": Vector(0, 1, 0),
|
|
"z": Vector(0, 0, 1),
|
|
"xy": Vector(1, 1, 0),
|
|
"yz": Vector(0, 1, 1),
|
|
"xz": Vector(1, 0, 1),
|
|
}
|
|
cq.selectors._SimpleStringSyntaxSelector._getVector = _getVector
|
|
|
|
cq.selectors._grammar = _makeGrammar() # make a grammar instance
|
|
cq.selectors._expression_grammar = cq.selectors._makeExpressionGrammar(cq.selectors._grammar)
|
|
|
|
cq.Workplane._filter = _filter
|