mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 10:11:46 +00:00
This commit is contained in:
@@ -55,19 +55,20 @@ filter_elements_grammar = lark.Lark(
|
|||||||
ifc_class: /Ifc\\w+/
|
ifc_class: /Ifc\\w+/
|
||||||
|
|
||||||
value: special | quoted_string | regex_string | unquoted_string
|
value: special | quoted_string | regex_string | unquoted_string
|
||||||
unquoted_string: /[^,.=\\s]+/
|
unquoted_string: /[^,.=><*!\\s]+/
|
||||||
regex_string: "/" /[^\\/]+/ "/"
|
regex_string: "/" /[^\\/]+/ "/"
|
||||||
quoted_string: ESCAPED_STRING
|
quoted_string: ESCAPED_STRING
|
||||||
|
|
||||||
special: null | true | false
|
special: null | true | false
|
||||||
|
|
||||||
comparison: not? equals | morethanequalto | lessthanequalto | morethan | lessthan
|
comparison: not? equals | morethanequalto | lessthanequalto | morethan | lessthan | not? contains
|
||||||
not: "!"
|
not: "!"
|
||||||
equals: "="
|
equals: "="
|
||||||
morethanequalto: ">="
|
morethanequalto: ">="
|
||||||
lessthanequalto: "<="
|
lessthanequalto: "<="
|
||||||
morethan: ">"
|
morethan: ">"
|
||||||
lessthan: "<"
|
lessthan: "<"
|
||||||
|
contains: "*="
|
||||||
null: "NULL"
|
null: "NULL"
|
||||||
true: "TRUE"
|
true: "TRUE"
|
||||||
false: "FALSE"
|
false: "FALSE"
|
||||||
@@ -557,18 +558,24 @@ class FacetTransformer(lark.Transformer):
|
|||||||
return tree
|
return tree
|
||||||
|
|
||||||
def comparison(self, args):
|
def comparison(self, args):
|
||||||
if args[0].data == "equals":
|
if args[0].data == "not":
|
||||||
return "="
|
comparison = args[1].data
|
||||||
elif args[0].data == "morethanequalto":
|
is_not = "!"
|
||||||
return ">="
|
|
||||||
elif args[0].data == "lessthanequalto":
|
|
||||||
return "<="
|
|
||||||
elif args[0].data == "morethan":
|
|
||||||
return ">"
|
|
||||||
elif args[0].data == "lessthan":
|
|
||||||
return "<"
|
|
||||||
else:
|
else:
|
||||||
return "!="
|
comparison = args[0].data
|
||||||
|
is_not = ""
|
||||||
|
|
||||||
|
return (
|
||||||
|
is_not
|
||||||
|
+ {
|
||||||
|
"equals": "=",
|
||||||
|
"morethanequalto": ">=",
|
||||||
|
"lessthanequalto": "<=",
|
||||||
|
"morethan": ">",
|
||||||
|
"lessthan": "<",
|
||||||
|
"contains": "*=",
|
||||||
|
}[comparison]
|
||||||
|
)
|
||||||
|
|
||||||
def keys(self, args):
|
def keys(self, args):
|
||||||
return self.value(args)
|
return self.value(args)
|
||||||
@@ -595,35 +602,42 @@ class FacetTransformer(lark.Transformer):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def compare(self, element_value, comparison, value):
|
def compare(self, element_value, comparison, value):
|
||||||
if element_value:
|
if isinstance(element_value, (list, tuple)):
|
||||||
if isinstance(element_value, (list, tuple)):
|
return any(self.compare(ev, comparison, value) for ev in element_value)
|
||||||
return any(self.compare(ev, comparison, value) for ev in element_value)
|
elif isinstance(value, str):
|
||||||
elif isinstance(value, re.Pattern):
|
if isinstance(element_value, int):
|
||||||
result = bool(value.match(element_value)) if element_value is not None else False
|
value = int(value)
|
||||||
elif isinstance(value, str):
|
elif isinstance(element_value, float):
|
||||||
if isinstance(element_value, int):
|
value = float(value)
|
||||||
value = int(value)
|
|
||||||
elif isinstance(element_value, float):
|
|
||||||
value = float(value)
|
|
||||||
|
|
||||||
if comparison == "=":
|
|
||||||
result = element_value == value
|
|
||||||
elif comparison == ">":
|
|
||||||
result = element_value > value
|
|
||||||
elif comparison == "<":
|
|
||||||
result = element_value < value
|
|
||||||
elif comparison == ">=":
|
|
||||||
result = element_value >= value
|
|
||||||
elif comparison == "<= ":
|
|
||||||
result = element_value <= value
|
|
||||||
else:
|
|
||||||
result = element_value != value
|
|
||||||
|
|
||||||
elif value in (None, True, False):
|
if isinstance(element_value, (int, float)):
|
||||||
result = element_value is value
|
operator = comparison.lstrip("!")
|
||||||
else:
|
if operator == ">=":
|
||||||
result = False
|
result = element_value >= value
|
||||||
return result
|
elif operator == "<=":
|
||||||
|
result = element_value <= value
|
||||||
|
elif operator == ">":
|
||||||
|
result = element_value > value
|
||||||
|
elif operator == "<":
|
||||||
|
result = element_value < value
|
||||||
|
else:
|
||||||
|
result = element_value == value # Tolerance?
|
||||||
|
elif isinstance(element_value, str):
|
||||||
|
operator = comparison.lstrip("!")
|
||||||
|
if operator == "*=":
|
||||||
|
result = value in element_value
|
||||||
|
else:
|
||||||
|
result = element_value == value
|
||||||
|
else:
|
||||||
|
result = element_value == value
|
||||||
|
elif isinstance(value, re.Pattern):
|
||||||
|
result = bool(value.match(element_value)) if element_value is not None else False
|
||||||
|
elif value in (None, True, False):
|
||||||
|
result = element_value is value
|
||||||
|
|
||||||
|
if comparison.startswith("!"):
|
||||||
|
return not result
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Selector:
|
class Selector:
|
||||||
|
|||||||
@@ -192,6 +192,20 @@ class TestFilterElements(test.bootstrap.IFC4):
|
|||||||
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Status": ["New"]})
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Status": ["New"]})
|
||||||
assert subject.filter_elements(self.file, "IfcWall, Pset_WallCommon.Status=New") == {element}
|
assert subject.filter_elements(self.file, "IfcWall, Pset_WallCommon.Status=New") == {element}
|
||||||
|
|
||||||
|
def test_selecting_by_property_with_comparisons(self):
|
||||||
|
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
|
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foobar")
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Baz": 123})
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, Foobar.Baz>100") == {element}
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, Foobar.Baz<100") == set()
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, Foobar.Baz>=100") == {element}
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, Foobar.Baz<=100") == set()
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": "Bar"})
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, Foobar.Foo*=ar") == {element}
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, Foobar.Foo!*=ar") == {element2}
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, Foobar.Foo*=Foo") == set()
|
||||||
|
|
||||||
def test_selecting_by_classification(self):
|
def test_selecting_by_classification(self):
|
||||||
project = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject")
|
project = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject")
|
||||||
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
|
|||||||
Reference in New Issue
Block a user