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
(showing TransformableObject
or .3dm
files).
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)
-
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)
-
max_select: maximum amount of objects the user is allowed to select
geometry = vkt.GeometryMultiSelectField("Select Geometries", max_select=5)
-
min_select: minimum amount of objects the user needs to select
geometry = vkt.GeometryMultiSelectField("Select Geometries", min_select=3)
-
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. This also works with
.3dm files, in which case the Name
parameter of an objects attributes will be used as an identifier.
- 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))