First Commit

This commit is contained in:
2026-05-31 10:17:09 +07:00
commit 17a9c69379
4547 changed files with 1170384 additions and 0 deletions
@@ -0,0 +1,33 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2025 Thomas Krijnen <thomas@aecgeeks.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/>.
"""
Coordinate Geometry (cogo) functions primarily for survey points and control monument for layout, parcels, etc.
"""
from .add_survey_point import add_survey_point
from .assign_survey_point import assign_survey_point
from .bearing2dd import bearing2dd
from .edit_survey_point import edit_survey_point
__all__ = [
"add_survey_point",
"assign_survey_point",
"bearing2dd",
"edit_survey_point",
]
@@ -0,0 +1,60 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2025 Thomas Krijnen <thomas@aecgeeks.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/>.
from typing import Union
import ifcopenshell
import ifcopenshell.api.spatial
import ifcopenshell.util.representation
from ifcopenshell import entity_instance
def add_survey_point(
file: ifcopenshell.file, survey_point: entity_instance, site: Union[entity_instance, None] = None
) -> entity_instance:
"""
Adds a single survey point to the model based on IFC Concept Template 4.1.7.1.2.5.
Survey points are located relative to IfcRepresentationContext.WorldCoordinateSystem
:param survey_point: The survey point
:return: an IfcAnnotation entity
Example:
.. code:: python
annotation = ifcopenshell.api.cogo.add_survey_point(file,file.createIfcCartesianPoint(4000.0,3500.0)))
"""
context = ifcopenshell.util.representation.get_context(file, "Model", "Annotation", "MODEL_VIEW")
shape_representation = file.createIfcShapeRepresentation(
ContextOfItems=context, RepresentationIdentifier="Annotation", RepresentationType="Point", Items=[survey_point]
)
representation = file.createIfcProductDefinitionShape(Representations=[shape_representation])
annotation = file.createIfcAnnotation(
ifcopenshell.guid.new(),
ObjectPlacement=context.WorldCoordinateSystem,
Representation=representation,
PredefinedType="SURVEY",
)
if site == None:
site = file.by_type("IfcSite")[0]
ifcopenshell.api.spatial.assign_container(file, relating_structure=site, products=[annotation])
return annotation
@@ -0,0 +1,38 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2025 Thomas Krijnen <thomas@aecgeeks.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/>.
from ifcopenshell import entity_instance
def assign_survey_point(annotation: entity_instance, survey_point: entity_instance):
"""
Assigns a coordinate point to a survey point annotation
:param annotaton: The survey point annotation
:param survey_point: The survey point
:return: None
Example:
.. code:: python
annotation = ifcopenshell.api.cogo.add_survey_point(file,file.createIfcCartesianPoint(4000.0,3500.0)))
ifcopenshell.api.cogo.assign_surve_point(annotation,file.createIfcCartesianPoint(4000.0,3500.0,100.0))
"""
annotation.Representation.Representations[0].Items = [survey_point]
@@ -0,0 +1,106 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2025 Thomas Krijnen <thomas@aecgeeks.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.util.geolocation
def bearing2dd(bearing: str) -> float:
"""
Converts a quadrant bearing string to decimal degrees
The format of the string is "N|S dd (mm (ss.s)) E|W"
where:
N|S is N or S for North or South
dd is degree (required)
mm is minute (optional, but required if second is provided)
ss.s is second (required)
E|W is E or W for East or West
:param str: the bearing string
:return: Angle in radian
"""
error_msg = "Invalid bearing string"
bearing = bearing.strip() # trim external white space
bearing = " ".join(bearing.split()) # make sure all parts separated by a single space
parts = bearing.split()
nParts = len(parts)
if nParts < 3 or 5 < nParts:
raise ValueError(error_msg)
cY = parts[0]
cY = cY.upper()
if cY != "N" and cY != "S":
raise ValueError(error_msg)
cX = parts[-1]
cX = cX.upper()
if cX != "E" and cX != "W":
raise ValueError(error_msg)
d = 0
m = 0
s = 0.0
ms = 0
if nParts == 3:
d = int(parts[1])
elif nParts == 4:
d = int(parts[1])
m = int(parts[2])
elif nParts == 5:
d = int(parts[1])
m = int(parts[2])
s = float(parts[3])
# s in a decimal number
# need to break it into whole seconds and milliseconds
ms = 100.0 * (s - int(s))
s = int(s)
if d < 0 or (m < 0 or 60 <= m) or (s < 0 or 60 <= s) or ms < 0:
raise ValueError(error_msg)
if cY == "N" and cX == "E":
angle = 90.0
sign = -1.0
elif cY == "N" and cX == "W":
angle = 90.0
sign = 1.0
elif cY == "S" and cX == "E":
angle = 270.0
sign = 1.0
elif cY == "S" and cX == "W":
angle = 270.0
sign = -1.0
try:
dms = ifcopenshell.util.geolocation.dms2dd(d, m, s, ms)
except ValueError:
raise ValueError(error_msg)
if dms < 0.0 or 90.0 < dms:
raise ValueError(error_msg)
angle += sign * dms
# S 90 E will evaluate to 360
if angle == 360.0:
angle = 0.0
return angle
@@ -0,0 +1,40 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2025 Thomas Krijnen <thomas@aecgeeks.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/>.
from ifcopenshell import entity_instance
def edit_survey_point(annotation: entity_instance, x: float, y: float, z: float = 0.0):
"""
Edits the location of a previously defined survey point
:param survey_point: The survey point
:return: None
Example:
.. code:: python
annotation = ifcopenshell.api.cogo.add_survey_point(file,file.createIfcCartesianPoint(4000.0,3500.0)))
ifcopenshell.api.cogo.edit_surve_point(annotation,3500.0,2000.0)
"""
if annotation.Representation.Representations[0].Items[0].Dim == 2:
annotation.Representation.Representations[0].Items[0].Coordinates = (x, y)
else:
annotation.Representation.Representations[0].Items[0].Coordinates = (x, y, z)