mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 19:27:10 +00:00
remove duplicated add_feature method
It was moved to feature module in 03bfd828e2
This commit is contained in:
@@ -1,152 +0,0 @@
|
|||||||
# IfcOpenShell - IFC toolkit and geometry engine
|
|
||||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
|
||||||
#
|
|
||||||
# This file is part of IfcOpenShell.
|
|
||||||
#
|
|
||||||
# IfcOpenShell is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# IfcOpenShell is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Lesser General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
|
||||||
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import ifcopenshell
|
|
||||||
import ifcopenshell.api.owner
|
|
||||||
import ifcopenshell.api.geometry
|
|
||||||
import ifcopenshell.api.aggregate
|
|
||||||
import ifcopenshell.guid
|
|
||||||
import ifcopenshell.util.element
|
|
||||||
import ifcopenshell.util.placement
|
|
||||||
|
|
||||||
|
|
||||||
def add_feature(
|
|
||||||
file: ifcopenshell.file, feature: ifcopenshell.entity_instance, element: ifcopenshell.entity_instance
|
|
||||||
) -> ifcopenshell.entity_instance:
|
|
||||||
"""Create a projecting, voiding, or surface feature in an element
|
|
||||||
|
|
||||||
There are three main types of features: those that add, remove, or
|
|
||||||
influence geometry of a parent object.
|
|
||||||
|
|
||||||
The most common of these is an opening. For example, it is often necessary
|
|
||||||
to cut out openings in elements like walls and slabs to make space to
|
|
||||||
insert doors, windows, and other services that go through these
|
|
||||||
penetrations.
|
|
||||||
|
|
||||||
Whereas it is possible to simply draw the wall as a rectangle with a
|
|
||||||
hole in it for the opening, often these openings have specific meanings.
|
|
||||||
For example, an opening might be filled with a window, and so when the
|
|
||||||
window moves, the opening should move with it. Alternatively, the
|
|
||||||
opening itself might have fire or acoustic requirements, such that any
|
|
||||||
service or equipment passing through that space must also comply with
|
|
||||||
those requirements. For these types of semantic openings, you should
|
|
||||||
have a distinct opening element which voids your regular element. For
|
|
||||||
example, your wall will still be a rectangular prism with no hole in it,
|
|
||||||
and a separate opening element will have a box representing the extents
|
|
||||||
of the opening for a window. The opening element will automatically
|
|
||||||
perform a geometric boolean operation to cut out the wall's geometry.
|
|
||||||
|
|
||||||
Whenever you have an opening in you project, you should determine
|
|
||||||
whether or not the opening is semantic (i.e. should be represented by a
|
|
||||||
distinct opening object) or non-semantic (i.e. should simply be
|
|
||||||
booleaned or be part of the shape of the object).
|
|
||||||
|
|
||||||
:param feature: The IfcFeatureElement to affect the element.
|
|
||||||
:type feature: ifcopenshell.entity_instance
|
|
||||||
:param element: The IfcElement to add the feature to.
|
|
||||||
:type element: ifcopenshell.entity_instance
|
|
||||||
:return: The new IfcRelVoidsElement relationship
|
|
||||||
:rtype: ifcopenshell.entity_instance
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
# A bit of preparation, let's create some geometric contexts since
|
|
||||||
# we want to create some geometry for our wall and opening.
|
|
||||||
model3d = ifcopenshell.api.context.add_context(model, context_type="Model")
|
|
||||||
body = ifcopenshell.api.context.add_context(model,
|
|
||||||
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model3d)
|
|
||||||
|
|
||||||
# Create a wall
|
|
||||||
wall = ifcopenshell.api.root.create_entity(model, ifc_class="IfcWall")
|
|
||||||
|
|
||||||
# Let's use the "3D Body" representation we created earlier to add a
|
|
||||||
# new wall-like body geometry, 5 meters long, 3 meters high, and
|
|
||||||
# 200mm thick
|
|
||||||
representation = ifcopenshell.api.geometry.add_wall_representation(model,
|
|
||||||
context=body, length=5, height=3, thickness=0.2)
|
|
||||||
ifcopenshell.api.geometry.assign_representation(model,
|
|
||||||
product=wall, representation=representation)
|
|
||||||
|
|
||||||
# Place our wall at the origin
|
|
||||||
ifcopenshell.api.geometry.edit_object_placement(model, product=wall)
|
|
||||||
|
|
||||||
# Create an opening, such as for a service penetration with fire and
|
|
||||||
# acoustic requirements.
|
|
||||||
opening = ifcopenshell.api.root.create_entity(model, ifc_class="IfcOpeningElement")
|
|
||||||
|
|
||||||
# Let's create an opening representation of a 950mm x 2100mm door.
|
|
||||||
# Notice how the thickness is greater than the wall thickness, this
|
|
||||||
# helps resolve floating point resolution errors in 3D.
|
|
||||||
representation = ifcopenshell.api.geometry.add_wall_representation(model,
|
|
||||||
context=body, length=.95, height=2.1, thickness=0.4)
|
|
||||||
ifcopenshell.api.geometry.assign_representation(model,
|
|
||||||
product=opening, representation=representation)
|
|
||||||
|
|
||||||
# Let's shift our door 1 meter along the wall and 100mm along the
|
|
||||||
# wall, to create a nice overlap for the opening boolean.
|
|
||||||
matrix = np.identity(4)
|
|
||||||
matrix[:,3] = [1, -.1, 0, 0]
|
|
||||||
ifcopenshell.api.geometry.edit_object_placement(model, product=opening, matrix=matrix)
|
|
||||||
|
|
||||||
# The opening will now void the wall.
|
|
||||||
ifcopenshell.api.void.add_feature(model, feature=opening, element=wall)
|
|
||||||
"""
|
|
||||||
if feature.is_a("IfcFeatureElementSubtraction"):
|
|
||||||
rels = feature.VoidsElements
|
|
||||||
ifc_class = "IfcRelVoidsElement"
|
|
||||||
elif feature.is_a("IfcFeatureElementAddition"):
|
|
||||||
rels = feature.ProjectsElements
|
|
||||||
ifc_class = "IfcRelProjectsElement"
|
|
||||||
elif feature.is_a("IfcSurfaceFeature"):
|
|
||||||
if file.schema == "IFC4":
|
|
||||||
return ifcopenshell.api.aggregate.assign_object(file, [feature], element)
|
|
||||||
rels = feature.AdheresToElement
|
|
||||||
ifc_class = "IfcRelAdheresToElement"
|
|
||||||
|
|
||||||
if rels:
|
|
||||||
if rels[0][4] == element:
|
|
||||||
return rels[0]
|
|
||||||
elif ifc_class == "IfcRelAdheresToElement" and len(rels[0].RelatedSurfaceFeatures) != 1:
|
|
||||||
rels[0].RelatedSurfaceFeatures = list(set(rels[0].RelatedSurfaceFeatures) - {feature})
|
|
||||||
else:
|
|
||||||
history = rels[0].OwnerHistory
|
|
||||||
file.remove(rels[0])
|
|
||||||
if history:
|
|
||||||
ifcopenshell.util.element.remove_deep2(file, history)
|
|
||||||
|
|
||||||
rel = file.create_entity(
|
|
||||||
ifc_class,
|
|
||||||
ifcopenshell.guid.new(),
|
|
||||||
ifcopenshell.api.owner.create_owner_history(file),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
element,
|
|
||||||
[feature] if ifc_class == "IfcRelAdheresToElement" else feature,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (placement := feature.ObjectPlacement) and placement.is_a("IfcLocalPlacement"):
|
|
||||||
ifcopenshell.api.geometry.edit_object_placement(
|
|
||||||
file,
|
|
||||||
product=feature,
|
|
||||||
matrix=ifcopenshell.util.placement.get_local_placement(placement),
|
|
||||||
is_si=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
return rel
|
|
||||||
Reference in New Issue
Block a user