mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Alignment api update (#6817)
* Some basic COGO survey points functions * Update alignment api Includes defining alignment segment by segment, automatic geometry definitions, and automatric stationing and referents * Fixes bonsai import alignment from csv * Adds DMS angle conversion functions to COGO api * Updated per @civilx64 review comments * Fixes problem with segment representations * Fixes problem with segment transition codes * Allows for compound vertical and horizontal curves * Implements callbacks for referent naming * Renames angle_from_bearing to bearing2dd for consistency with ifcopenshell.util.geolocation.dms2dd. Removes angle_from_dms because it duplicates dms2dd * Documents register_referent_name_callback * Fixes all sorts of problems with Cant/SegRefCurve implementation * refactor referent unit tests to use a fixture for test setup * lint with black --------- Co-authored-by: Scott Lecher <civilx64@gmail.com>
This commit is contained in:
@@ -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 .edit_survey_point import edit_survey_point
|
||||
from .bearing2dd import bearing2dd
|
||||
|
||||
__all__ = [
|
||||
"add_survey_point",
|
||||
"assign_survey_point",
|
||||
"edit_survey_point",
|
||||
"bearing2dd",
|
||||
]
|
||||
@@ -0,0 +1,47 @@
|
||||
# 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
|
||||
from ifcopenshell import entity_instance
|
||||
import typing
|
||||
|
||||
def add_survey_point(file: ifcopenshell.file, survey_point: entity_instance, site:entity_instance = 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/>.
|
||||
|
||||
import ifcopenshell
|
||||
from ifcopenshell import entity_instance
|
||||
import typing
|
||||
|
||||
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.
|
||||
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.*(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.
|
||||
sign = -1.
|
||||
elif cY == 'N' and cX == 'W':
|
||||
angle = 90.
|
||||
sign = 1.
|
||||
elif cY == 'S' and cX == 'E':
|
||||
angle = 270.
|
||||
sign = 1.
|
||||
elif cY == 'S' and cX == 'W':
|
||||
angle = 270.
|
||||
sign = -1.
|
||||
|
||||
try:
|
||||
dms = ifcopenshell.util.geolocation.dms2dd(d,m,s,ms)
|
||||
except ValueError:
|
||||
raise ValueError(error_msg)
|
||||
|
||||
if dms < 0. or 90. < dms:
|
||||
raise ValueError(error_msg)
|
||||
|
||||
angle += sign*dms
|
||||
|
||||
# S 90 E will evaluate to 360
|
||||
if angle == 360.:
|
||||
angle = 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/>.
|
||||
|
||||
import ifcopenshell
|
||||
from ifcopenshell import entity_instance
|
||||
import typing
|
||||
|
||||
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))
|
||||
Reference in New Issue
Block a user