Geometry selection
The geometry selection fields, enable the user to select geometries in an
IFCView
or a
GeometryView
.
For a more technical API reference, please see the following pages:
GeometrySelectField - select a geometry
The GeometrySelectField
enables the user to select a single (sub-)geometry in a geometric view.
It should be used in combination with an IFCView
or GeometryView
.
import viktor as vkt
class Parametrization(vkt.Parametrization):
geometry = vkt.GeometrySelectField("Select Geometry")
The user input can be obtained through the params argument and can have the following values:
string
: when a geometry is selectedNone
: when empty
Expand to see all available arguments
In alphabetical order:
-
default: a default value will be prefilled
geometry = vkt.GeometrySelectField("Select Geometry", default="cube1")
-
description: add a tooltip with additional information
geometry = vkt.GeometrySelectField("Select Geometry", description="This field represents the ...")
-
flex: the width of the field between 0 and 100 (default=33)
geometry = vkt.GeometrySelectField("Select Geometry", flex=50)
-
max_select: maximum amount of objects the user is allowed to select
geometry = vkt.GeometrySelectField("Select Geometry", max_select=5)
-
min_select: minimum amount of objects the user needs to select
geometry = vkt.GeometrySelectField("Select Geometry", min_select=3)
-
name: defines the position of the parameter in the params
geometry = vkt.GeometrySelectField("Select Geometry", name="g") # obtained using params.g
-
view: view method to which the field is connected (default: first GeometryView / IFCView)
geometry = vkt.GeometrySelectField("Select Geometry", view="geometry_view")
-
visible: can be used when the visibility depends on other input fields
geometry = vkt.GeometrySelectField("Select Geometry", visible=vkt.Lookup("another_field"))
See 'Hide a field' for elaborate examples.
Select multiple geometries
The GeometryMultiSelectField
enables the user to select multiple (sub-)geometries in a geometric view.
It should be used in combination with an IFCView
or GeometryView
.
import viktor as vkt
class Parametrization(vkt.Parametrization):
geometries = vkt.GeometryMultiSelectField("Select Geometries")
The user input can be obtained through the params argument and can have the following values:
- list of
string
: when geometries are selected - empty list when empty
Expand to see all available arguments
In alphabetical order:
-
default: a default value will be prefilled
geometries = vkt.GeometryMultiSelectField("Select Geometries", default=["cube1", "cube3"])
-
description: add a tooltip with additional information
geometries = vkt.GeometryMultiSelectField("Select Geometries", description="This field represents the ...")
-
flex: the width of the field between 0 and 100 (default=33)
geometries = vkt.GeometryMultiSelectField("Select Geometries", flex=50)
-
name: defines the position of the parameter in the params
geometries = vkt.GeometryMultiSelectField("Select Geometries", name="g") # obtained using params.g
-
view: view method to which the field is connected (default: first GeometryView / IFCView)
geometries = vkt.GeometryMultiSelectField("Select Geometries", view="geometry_view")
-
visible: can be used when the visibility depends on other input fields
geometries = vkt.GeometryMultiSelectField("Select Geometries", visible=vkt.Lookup("another_field"))
See 'Hide a field' for elaborate examples.
Example
To support geometry selection, the following parts need to be implemented in the app:
- IFCView
- GeometryView
- Create an IFCView in the controller
- Create a
FileField
andGeometrySelectField
(orGeometryMultiSelectField
) in the parametrization - Use the
identifier
retrieved from the params in subsequent calculations
An IFC-file contains unique identifiers per geometry feature.
import viktor as vkt
import ifcopenshell
import ifcopenshell.util.element
from pathlib import Path
from tempfile import NamedTemporaryFile
class Parametrization(vkt.Parametrization):
ifc = vkt.FileField("Please provide an IFC file")
geometry = vkt.GeometrySelectField("Select Geometry")
class Controller(vkt.Controller):
parametrization = Parametrization
@vkt.IFCAndDataView("IFC", x_axis_to_right=True)
def get_ifc_and_data_view(self, params, **kwargs):
ifc_file = params.ifc.file
if selected_geometry := params.geometry: # If user has made a selection, add its properties to `data`
# parse your ifc file (e.g. with ifcopenshell as below)
with NamedTemporaryFile(suffix=".ifc", delete=False, mode="w") as temp_f:
temp_f.write(ifc_file.getvalue())
model = ifcopenshell.open(Path(temp_f.name))
elem = model.by_id(int(selected_geometry))
# See https://wiki.osarch.org/index.php?title=IFC_attributes_and_properties
# for a list of available IFC attributes and properties
data_items = []
for key, val in ifcopenshell.util.element.get_psets(elem).items():
sub_data_items = []
for k,v in val.items():
sub_data_items.append(vkt.DataItem(k, v))
data_items.append(vkt.DataItem(key, '', subgroup=vkt.DataGroup(*sub_data_items)))
data = vkt.DataGroup(*data_items)
else:
data = vkt.DataGroup(vkt.DataItem('No geometries selected', ''))
return vkt.IFCAndDataResult(ifc=ifc_file, data=data)
- Create a GeometryView in the controller
- Create a
GeometrySelectField
(orGeometryMultiSelectField
) in the parametrization - Use the
identifier
retrieved from the params in subsequent calculations
Identifiers can be assigned to the VIKTOR geometry objects, to make them selectable in the view.
- If several objects have an identifier assigned, then only these objects will be selectable in the View.
- If none of the objects in the GeometryResult have an identifier assigned, default identifiers are assigned to all of them (enabling them for selection).
- If there are multiple objects with the same name, a number will automatically be appended to enforce uniqueness.
import viktor as vkt
class Parametrization(vkt.Parametrization):
geometry = vkt.GeometrySelectField("Select Geometry")
geometries = vkt.GeometryMultiSelectField("Select Geometries")
class Controller(vkt.Controller):
parametrization = Parametrization
@vkt.GeometryAndDataView('Geometry', x_axis_to_right=True)
def get_geometry_and_data_view(self, params, **kwargs):
cubes = {
'cube1': vkt.SquareBeam(1, 1, 5, identifier="cube1"),
'cube2': vkt.SquareBeam(1, 4, 1, identifier="cube2"),
'cube3': vkt.SquareBeam(3, 1, 1, identifier="cube3")
}
# Calculate data
if selected_geometry := params.geometry:
volume = cubes[selected_geometry].inner_volume
data_1 = vkt.DataItem('Volume of GeometrySelectField', volume, suffix="m3")
else:
data_1 = vkt.DataItem('No geometry selected in GeometrySelectField', '')
if selected_geometries := params.geometries:
volume = sum(cubes[selected_geometry].inner_volume for selected_geometry in selected_geometries)
data_2 = vkt.DataItem('Volume of GeometryMultiSelectField', volume, suffix="m3")
else:
data_2 = vkt.DataItem('No geometries selected in GeometryMultiSelectField', '')
return vkt.GeometryAndDataResult(geometry=cubes.values(), data=vkt.DataGroup(data_1, data_2))