upxo.geoEntities.mulsline2d module
Multi-straight line 2D geometric entity module for UPXO.
This module provides multi-straight-line (polyline) representations in 2D space. It supports closed and open polylines with operations for node/line management, spatial queries, adjacent relationship detection, and geometric transformations.
Core Classes
MSline2d: Multi-straight-line in 2D (collection of connected line segments).ring2d: Ring structure in 2D (to be further developed).mulring2d: Multiple rings in 2D (to be further developed).
Key Features
Line chain construction from various input formats (node points, coordinates, existing lines).
Node and line enumeration, spacing, and connectivity checks.
Adjacency and spatial relationship detection between polylines.
Centroid and length calculations.
Open/closed topology management.
Node coordinate access and updates.
Spatial tree indexing for nearest-neighbor queries.
Point location finding within polyline node sequences.
Plotting and visualization support.
Applications
Non-conformal to conformal geometry conversion.
Hierarchical grain structure feature generation.
General geometry operations and polyline manipulation.
Boundary and edge representation in meshing and simulation.
Usage
from upxo.geoEntities.mulsline2d import MSline2d
Coordinate System
Standard 2D Cartesian with notation (X+, Y+) = (right, up):
Y+ | | | |
X- | X+ —–+—–+—–O—–+—–+—–
Y-
@author: Dr. Sunil Anandatheertha
Examples
- Construct from line objects:
>>> from upxo.geoEntities.mulsline2d import MSline2d >>> from upxo.geoEntities.sline2d import Sline2d >>> lines = [ ... Sline2d(0, 0, 1, 1), ... Sline2d(1, 1, 2, 2), ... Sline2d(2, 2, 3, 1) ... ] >>> msl = MSline2d.from_lines(lines, close=False) >>> msl.nlines, msl.nnodes (3, 4)
- Construct from coordinates:
>>> coords = [(0, 0), (1, 1), (2, 2), (3, 1)] >>> msl = MSline2d.by_coords(coords, close=True) >>> msl.length >>> msl.centroid
- Query relationships:
>>> msl1 = MSline2d.by_coords([(0, 0), (1, 1)]) >>> msl2 = MSline2d.by_coords([(1, 1), (2, 2)]) >>> msl1.do_i_precede(msl2) # Check if msl1 comes before msl2 True
- Find closest nodes:
>>> from upxo.geoEntities.point2d import Point2d >>> msl = MSline2d.by_coords([(0, 0), (2, 0), (4, 0)]) >>> closest = msl.find_closest_nodes(Point2d(1.5, 0.5))
See also
-, -, -
- class upxo.geoEntities.mulsline2d.MSline2d(nodes=None, llist=None, closed=None)[source]
Bases:
objectMulti-straight-line (polyline) entity in 2D for UPXO.
A connected chain of
Sline2dline segments sharing end-nodes. Supports open and closed topologies.Examples
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d e0 = sl2d(0.0, 0.0, 1.0, 1.0) e1 = sl2d(1.0, 1.0, 1.5, 1.5) e2 = sl2d(1.5, 1.5, 2.5, 2.5) e3 = sl2d(2.5, 2.5, 4.0, 4.0) e4 = sl2d(4.0, 4.0, 4.0, 6.0) me = msl2d.from_lines([e0, e1, e2, e3, e4], close=False)
- EPS_coord_coincide = 1e-08
- lines
- nodes
- closed
- features
- classmethod from_lines(llist, close=True)[source]
Construct a multi-straight-line 2D from a list of Sline2d objects.
- Parameters:
- Returns:
Assembled polyline.
- Return type:
Examples
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d e0 = sl2d(0.0, 0.0, 1.0, 1.0) e1 = sl2d(1.0, 1.0, 1.5, 1.5) e2 = sl2d(1.5, 1.5, 2.5, 2.5) e3 = sl2d(2.5, 2.5, 4.0, 4.0) e4 = sl2d(4.0, 4.0, 4.0, 6.0) me_closed = msl2d.from_lines([e0, e1, e2, e3, e4], close=True) me_open = msl2d.from_lines([e0, e1, e2, e3, e4], close=False)
- classmethod by_nodes(nodes, close=True)[source]
Construct a multi-straight-line 2D from a list of Point2d nodes.
- Parameters:
- Returns:
Assembled polyline.
- Return type:
Examples
from upxo.geoEntities.mulsline2d import MSline2d from upxo.geoEntities.point2d import Point2d nodes = [Point2d(0, 0), Point2d(1, 1), Point2d(2, 2), Point2d(3, 3), Point2d(5, 5)] MSline2d.by_nodes(nodes).lines
- classmethod by_coords(coords, close=True)[source]
Construct a multi-straight-line 2D from a sequence of (x, y) coordinates.
- Parameters:
- Returns:
Assembled polyline.
- Return type:
Examples
from upxo.geoEntities.mulsline2d import MSline2d import numpy as np coords = np.array([(0,0), (1,1), (2,2), (3,3), (5,5)]) msl = MSline2d.by_coords(coords) msl.lines msl.nodes
- classmethod by_walk(var_l='constant', var_ang='constant', specs={'max_total_length': 10, 'mean_length': 1, 'min_total_length': 8, 'n': 5})[source]
Generate polyline by “walking” with variable step length/angle.
- Parameters:
Notes
To be developed.
- property nlines
Return number of lines.
- Returns:
Number of constituent line segments.
- Return type:
- property centroid
Compute and return centroid of the polyline.
- Returns:
Mean coordinate (x, y) of all nodes.
- Return type:
- property centroid_p2dl
Return centroid as p2d_leanest point object.
- Returns:
Lightweight point object at polyline centroid.
- Return type:
- property length
Return total length of all lines in polyline.
- Returns:
Sum of all individual line lengths.
- Return type:
- property lengths
Return individual line lengths as list.
- Returns:
Lengths of each line in the polyline.
- Return type:
- property nnodes
Return number of polyline nodes.
- Returns:
Node count, excluding the duplicate closing node when closed.
- Return type:
- property coords
Get all node coordinates as 2D array.
- Returns:
Array of shape (n_nodes, 2) with (x, y) coordinates.
- Return type:
- property tree
Build spatial KD-tree index for neighbor queries.
- Returns:
KD-tree constructed from node coordinates.
- Return type:
scipy.spatial.cKDTree
- property length_mean
Return mean length of all line segments.
- Returns:
Total length divided by number of lines.
- Return type:
- property gradients
Return gradient of every line.
- Returns:
Gradient value for each constituent line.
- Return type:
- property get_nodes
Return unique nodes in the multi-straight-line object.
- Returns:
Unique node coordinate rows.
- Return type:
- get_node_coords()[source]
Extract and return all node coordinates as array.
- Returns:
Array of shape (n_nodes, 2) with (x, y) coordinates of each node.
- Return type:
- property mid_nodes
Return midpoint nodes of all lines.
- Returns:
Mid-point of each line segment in the polyline.
- Return type:
Examples
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) MULLINE.mid_nodes MULLINE.centroid_p2dl
- property line_ids
Return memory id of each line.
- flip(saa=True, throw=False)[source]
Reverse the order of lines in the polyline.
- Parameters:
- Returns:
Flipped polyline if
throwis True, elseNone.- Return type:
MSline2d or None
Examples
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) MULLINE.flip() MULLINE.lines MULLINE.nodes
- do_i_precede(multisline2d)[source]
Check if self spatially precedes the input multisline2d.
- Parameters:
multisline2d (MSline2d) – Candidate successor polyline.
- Returns:
i_precede (bool) – True if self immediately precedes
multisline2d.flip_needed (bool) – True if
multisline2dmust be flipped to achieve nodal continuity with self.
- do_i_proceed(multisline2d)[source]
Check if self spatially comes after the input multisline2d.
- Parameters:
multisline2d (MSline2d) – Candidate predecessor polyline.
- Returns:
i_proceed (bool) – True if self immediately succeeds
multisline2d.flip_needed (bool) – True if
multisline2dmust be flipped to achieve nodal continuity with self.
- is_adjacent(multisline2d)[source]
Check spatial adjacency with another multiline.
- Parameters:
multisline2d (MSline2d) – Another multi-straight-line object to test.
- Returns:
(is_adjacent_bool, left_relation, right_relation) tuple.
- Return type:
Notes
Checks if multiline is immediately preceded or succeeded by input.
- find_spatially_next_multisline2d(multislines2d)[source]
From a list of multisline2d objects, multislines2d, find the ones which come spatially immediately after self.
- has_coord(coord, return_flags=False)[source]
Check if coordinate exists in polyline node sequence.
- Parameters:
coord (array-like) – 2D coordinate (x, y) to search for.
return_flags (bool, optional) – If True, return boolean flags array.
- Returns:
If return_flags=False: boolean indicating existence. If return_flags=True: (existence_bool, flags_array) tuple.
- Return type:
bool or (bool, numpy.ndarray)
- find_coord_location(coord)[source]
Find index location of coordinate in node sequence.
- Parameters:
coord (array-like) – 2D coordinate (x, y) to search for.
- Returns:
Index array if coordinate found, None if not found.
- Return type:
numpy.ndarray or None
- extract_nodes()[source]
Extract all unique nodes from polyline lines.
- Returns:
List of Point2d nodes (including closing node if closed).
- Return type:
- update_nodes()[source]
Update internal node list from current line definitions.
Notes
Reconstructs self.nodes from line start/end points, respecting open/closed topology.
- close(reclose=False)[source]
Close the self multi-straight line object.
- Parameters:
reclose (bool, optional) – If
True, append a closing line even when already closed.- Returns:
Updates
self.linesin place.- Return type:
None
Examples
- unclose()[source]
Remove the closing line.
- Returns:
Deletes the last line from
self.lines.- Return type:
None
- distances_nodes(points)[source]
Compute distances from every node to each given point.
- Parameters:
points (numpy.ndarray of shape (m, 2)) – Query points.
- Returns:
Euclidean distance from each node to each query point.
- Return type:
numpy.ndarray of shape (n_nodes, m)
Notes
Uses vectorised broadcasting:
points[:, np.newaxis]is broadcast against the node array so all pairwise distances are computed in one operation.Examples
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d import numpy as np lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) points = np.random.random((2, 2)) MULLINE.distances_nodes(points)
- find_closest_nodes(point)[source]
Find the closest node index (or indices) to a query point.
- Parameters:
point (array-like of shape (2,)) – Query point coordinates.
- Returns:
Index of the closest node, or a list of indices if multiple nodes are equidistant.
- Return type:
Examples
Example 1 — random query point:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d import numpy as np lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5)] MULLINE = msl2d.from_lines(lines, close=True) point = np.random.random(2) * np.random.randint(10) MULLINE.find_closest_nodes(point)
Example 2 — midpoint of first line:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5)] MULLINE = msl2d.from_lines(lines, close=True) point = lines[0].mid MULLINE.find_closest_nodes(point)
- add_nodes(nodes)[source]
Insert new nodes into the polyline by splitting existing lines.
- Parameters:
nodes (list of Point2d) – New nodes to insert. Each node is located on an existing line segment and splits it.
Notes
If a node does not lie on any line segment it is silently ignored. The internal node list is updated after each insertion.
Examples
Example 1 — insert two nodes on a 5-segment polyline:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d from upxo.geoEntities.point2d import Point2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] mulline = msl2d.from_lines(lines, close=True) mulline.add_nodes([Point2d(0.5, 0.5), Point2d(2.0, 2.0)]) mulline.lines
Example 2 — insert three nodes on a 6-segment polyline:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d from upxo.geoEntities.point2d import Point2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,5.0,4.0), sl2d(5.0,4.0,5.0,0.0)] mulline = msl2d.from_lines(lines, close=True) mulline.add_nodes([Point2d(0.5, 0.5), Point2d(2.0, 2.0), Point2d(1.75, 0)]) mulline.lines
- splice_nodes_and_lines(method='points', points=None, perform_checks=True)[source]
Splice/interpolate nodes and lines at specified points.
- Parameters:
Notes
To be developed.
- roll(roll_distance)[source]
Roll/rotate line order within the polyline chain.
- Parameters:
roll_distance (int) – Number of positions to roll lines.
Notes
Updates internal node list after rolling. Useful for changing polyline starting point while preserving connectivity.
- sub_divide(line_number=0, f=0.5)[source]
Sub-divide a single line in
self.linesat a fractional position.- Parameters:
Examples
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] me = msl2d.from_lines(lines, close=False) me.sub_divide(line_number=0, f=0.25) me.sub_divide(line_number=3, f=0.50) for i in range(5): me.sub_divide(line_number=i, f=0.50) me.lines
- remove_point_by_index(index=2, remove='previous_line')[source]
Remove a node at the given index by merging its adjacent line segments.
- Parameters:
index (int, optional) – Zero-based node index to remove.
remove ({'previous_line', 'next_line', 'both'}) – Which adjacent line to delete:
'previous_line'— extend the next line backward;'next_line'— extend the previous line forward;'both'— replace both adjacent lines with a new direct line.
Examples
Example 1 — remove via previous line:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) MULLINE.remove_point_by_index(index=2, remove='previous_line') MULLINE.lines
Example 2 — remove via next line:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) MULLINE.remove_point_by_index(index=2, remove='next_line') MULLINE.lines
Example 3 — remove both adjacent lines:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) MULLINE.remove_point_by_index(index=2, remove='both') MULLINE.lines
- remove_point_by_location(location=(None, None, None), remove='previous_line')[source]
Remove the node closest to a given location.
- Parameters:
location (array-like of shape (2,)) – Query coordinates used to find the closest node.
remove ({'previous_line', 'next_line', 'both'}) – Passed through to
remove_point_by_index().
Notes
If multiple nodes tie for closest, all are removed recursively. When only 2 lines remain and the closing line is redundant, the closing line is automatically deleted.
Examples
Example 1 — remove by endpoint coordinate:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) MULLINE.remove_point_by_location(location=lines[0].coord_i, remove='previous_line') MULLINE.lines
Example 2 — remove by midpoint coordinate:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) MULLINE.remove_point_by_location(location=lines[0].mid, remove='previous_line') MULLINE.lines
Example 3 — remove by random location:
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.sline2d import Sline2d as sl2d import numpy as np lines = [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5), sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)] MULLINE = msl2d.from_lines(lines, close=True) location = np.random.random(2) * np.random.randint(10) MULLINE.remove_point_by_location(location=location, remove='previous_line') MULLINE.lines
- plot(ax=None, connect_ends=False)[source]
Plot polyline on matplotlib axes.
- Parameters:
ax (matplotlib.axes.Axes, optional) – Axes object to plot on. If None, creates new figure/axes.
connect_ends (bool, optional) – If True, draw line connecting polyline start and end points.
- Returns:
Axes object with plotted polyline.
- Return type:
matplotlib.axes.Axes
Examples
>>> msl = MSline2d.by_coords([(0, 0), (1, 1), (2, 0)]) >>> ax = msl.plot()
- check_overlaping_points(tolerance=1e-08)[source]
Check for overlapping/duplicate nodes within tolerance.
- check_overlaping_lines()[source]
Check for overlapping line segments in polyline.
- Returns:
True if overlapping lines detected, None if to be completed.
- Return type:
bool or None
Notes
To be developed. Current implementation collects midpoints and gradients but does not perform overlap checks.
- clone()[source]
Return an independent copy of the node and line containers.
The node and line objects are shared with the original. That is safe for
smooth(), which replacesnodesandlineswith new lists and new interior points rather than mutating them, and it is far cheaper thancopy.deepcopy.
- smooth(max_smooth_level=2)[source]
Smooth the polyline by replacing node coordinates with local means.
- Parameters:
max_smooth_level (int, optional) – Number of smoothing passes applied via
mean_coordinates().
Notes
Terminal nodes (first and last) are preserved. If fewer than 3 nodes are present, no smoothing is performed.
Examples
from upxo.geoEntities.mulsline2d import MSline2d as msl2d from upxo.geoEntities.point2d import Point2d nodes = [Point2d(0.0, 0.0), Point2d(1.0, 0.0), Point2d(1.0, 1.0), Point2d(2.5, 2.0), Point2d(4.0, 2.0), Point2d(4.0, 6.0), Point2d(4.0, 8.0), Point2d(2.0, 8.0)] ml = msl2d.by_nodes(nodes, close=False) ax = ml.plot() ml.smooth(max_smooth_level=3) ax.plot(ml.coords[:, 0], ml.coords[:, 1])
- class upxo.geoEntities.mulsline2d.ring2d(segments=None, segids=None, segflips=None)[source]
Bases:
objectRing structure in 2D—closed polyline representation from multiple segments.
This class manages a collection of connected MSline2d (multi-straight-line) segments that form a closed ring/loop structure. It handles segment ordering, flipping, spatial continuity checks, and polygon conversion.
Notes
ring2dis in active development. Closure enforcement, reordering, and polygon generation are implemented; polygon meshing is not yet available.Name collision:
upxo.geoEntities.ring2d.ring2dis a separate, unrelated, currently-unused class (built onmuledge2drather thanMSline2dsegments). Mind the module path when importing.Examples
from upxo.geoEntities.mulsline2d import MSline2d, ring2d from upxo.geoEntities.sline2d import Sline2d as sl2d msl1 = MSline2d.from_lines( [sl2d(0.0,0.0,1.0,1.0), sl2d(1.0,1.0,1.5,1.5), sl2d(1.5,1.5,2.5,2.5)], close=False) msl2 = MSline2d.from_lines( [sl2d(2.5,2.5,4.0,4.0), sl2d(4.0,4.0,4.0,6.0)], close=False) msl3 = MSline2d.from_lines( [sl2d(4.0,6.0,4.0,8.0), sl2d(4.0,8.0,10.0,10.0)], close=False) msl4 = MSline2d.from_lines( [sl2d(0,0,20,10), sl2d(20,10,10,10)], close=False) R = ring2d([msl1, msl2, msl3, msl4]) R.assess_spatial_continuity()
- EPS_coord_coincide = 1e-08
- clone(seg_clones)[source]
Return a copy of this ring that uses cloned segments.
- Parameters:
seg_clones (dict) –
{id(original segment): cloned segment}. Segments missing from it are cloned and added, so a segment shared by several rings is cloned once and stays shared among the copies.
Notes
coords,conn0andconn1are not populated anywhere in the current geometrification/meshing pipeline before a ring is cloned, so this has had no observed effect; they are still copied by value rather than by reference so thatconnectivity1()orset_coords()called later on the original or the clone cannot silently corrupt the other, matching the “independent copy” this method promises.
- translate(dx, dy, seen=None)[source]
Translate every point of this ring by
(dx, dy), in place.Walks every Sline2d endpoint by object identity – junction points and consecutive-line nodes are shared across segments – so a point shared by several segments/lines is moved exactly once, then resyncs each Sline2d’s cached x0/y0/x1/y1 to match.
- Parameters:
seen (set, optional) –
{id(point): ...}of points already translated. Pass the same set across severaltranslatecalls (e.g. one per sibling ring in the same cluster) when their rings may share Point2d objects at a common wall, so a shared point is not translated once per ring that references it.
- translated_copy(dx, dy, seg_copies)[source]
Return a copy of this ring shifted by
(dx, dy)that shares no point or line with it; the original is not changed.MSline2d.cloneshares its point objects with the original, soclonefollowed bytranslate()would move the original too.- Parameters:
seg_copies (dict) –
{id(original segment): its translated copy}. Pass one dict for rings that may share walls, so a wall shared by several rings is copied once and stays shared among the copies.
- segments
- segids
- segflips
- nsegs
Proceed continuities, flips = self.assess_spatial_continuity(segments) if not all(continuities):
- if self.assess_possibility_of_continuity(segments):
self.get_continuity_enforcement_indices() self.set_spatial_continuity(enforce_indices)
- else:
raise ValueError(‘Invalid segments morphology passed.’)
- Type:
overlaps = self.assess_segment_point_overlaps(segments) # False
- add_segment_unsafe(segment)[source]
Add segment to ring without validation.
- Parameters:
segment (MSline2d) – Segment to append (no continuity checks).
- add_segid(segid)[source]
Add segment identifier to tracking list.
- Parameters:
segid (hashable) – Segment identifier to track.
- add_segflip(segflip)[source]
Add segment flip status flag.
- Parameters:
segflip (bool) – True if segment was flipped, False otherwise.
- check_closed()[source]
Check if ring is topologically closed.
- Returns:
True if end node of last segment connects to start node of first segment (within EPS_coord_coincide tolerance).
- Return type:
- close()[source]
Enforce topological closure by connecting end to start.
Notes
Adds first segment’s start node as last segment’s end node and updates internal node list.
- connectivity0(flip_if_possible=True)[source]
Assess closure of 1st & last segment with option to close if possible.
- Parameters:
flip_if_possible (bool, optional) – Whether to flip the last segment when doing so would close the ring.
- Returns:
closed (bool) –
Trueif the ring is already closed or has been closed.last_seg_flipped (bool) –
Trueif the last segment was flipped to achieve closure.flip_possible (bool) –
Truewhen closure is possible by flipping the last segment.
- connectivity1()[source]
Assess closure of all intermediate segments.
- Returns:
Updates
self.conn1with pairwise segment-continuity flags.- Return type:
None
- assess_segment_point_overlaps(line_check=False)[source]
Check all segments for duplicate/overlapping nodes.
- assess_reorder_requirement()[source]
Check if reordering or flipping of segments is needed.
Notes
To be developed. Currently evaluates closure status and potential flips needed to enforce continuity.
- set_coords()[source]
Build and cache coordinate array from all segments.
Notes
Combines node coordinates of all segments, skipping duplicate nodes at segment junctions.
- get_coords()[source]
Extract and return full coordinate array from ring.
- Returns:
Coordinates of all ring nodes.
- Return type:
- property centroid
Compute centroid of the ring shape.
- Returns:
Mean (x, y) coordinate of all ring nodes.
- Return type:
- create_coords_from_segments(force_close=False)[source]
Build coordinate array from all segments, respecting flips.
- Parameters:
force_close (bool, optional) – If True, append first coordinate to end to ensure closure.
- Returns:
Coordinates from all segments, concatenated in order.
- Return type:
- force_close_coordinates(coord, assess_first=True)[source]
Ensure coordinate array is closed (end connects to start).
- Parameters:
coord (numpy.ndarray) – Input coordinate array.
assess_first (bool, optional) – If True, check if already closed before forcing.
- Returns:
Closed coordinate array.
- Return type:
Notes
Unsafe. Not intended for user. Uses EPS_coord_coincide tolerance.
- create_polygon_from_segments()[source]
Convert ring to Shapely Polygon object.
- Returns:
Polygon representation of the ring.
- Return type:
shapely.geometry.Polygon
- create_polygon_from_coords()[source]
Create Shapely Polygon from coordinates.
- Returns:
Polygon from extracted ring coordinates.
- Return type:
shapely.geometry.Polygon
- property area
Compute area enclosed by ring polygon.
- Returns:
Area of ring polygon.
- Return type:
- property perimeter
Compute perimeter (boundary length) of ring.
- Returns:
Total perimeter of ring polygon.
- Return type:
- property is_closed
Check if ring is topologically closed.
- Returns:
True if ring forms a closed loop.
- Return type:
- property nsegments
Return number of segments in ring.
- Returns:
Count of constituent MSline2d segments.
- Return type:
- property ncoords
Return total number of nodes in ring.
- Returns:
Count of unique coordinate nodes.
- Return type:
- property tree
Build spatial KD-tree index for ring coordinates.
- Returns:
KD-tree for neighbor/distance queries on ring nodes.
- Return type:
scipy.spatial.cKDTree
- assess_spatial_continuity()[source]
From list of multisline2d, multislines2d, do all (i+1)^th multisline2d follow i^th multisline2d? with or without the need for flips.
- Returns:
continuity (bool) –
Truewhen all segments form a chain, irrespective of whether flips are needed.flip_needed (bool) –
Trueif any multi-line object needs flipping to ensure spatial continuity.i_precede_chain (list) –
do_i_precederesults for everyi:i+1pair.
- plot_segs(plot_centroid=False, centroid_text='', plot_coord_order=False, visualize_flip_req=False)[source]
Visualize ring segments with optional annotations.
- Parameters:
plot_centroid (bool, optional) – If True, plot ring centroid marker and label.
centroid_text (str, optional) – Label text for centroid.
plot_coord_order (bool, optional) – If True, plot coordinate connectivity with dashed line.
visualize_flip_req (bool, optional) – If True, use dashed lines for flipped segments.
- Returns:
Axes object with plotted segments (color-coded).
- Return type:
matplotlib.axes.Axes
- get_coords_newdef()[source]
Extract coordinates in new definition format.
- Returns:
(segment_coords_list, combined_coords) where: - segment_coords_list: List of coordinate arrays per segment - combined_coords: Concatenated coordinate array from all segments
- Return type:
- coords
- closed
- conn0
- conn1
- class upxo.geoEntities.mulsline2d.mulring2d(rings)[source]
Bases:
objectCollection of 2D ring objects with shared interface bookkeeping.
- Parameters:
rings (list) – Ring objects to be grouped into the multi-ring container.
Notes
The implementation is currently a placeholder for future multi-ring workflows. Existing notes below describe the intended data model and are retained for development continuity.
- rings
- build_points_list()[source]
Build a flat list of all points from the ring collection.
- Raises:
NotImplementedError – Always raised because point-list construction is not implemented.
- set_coords()[source]
Set coordinate arrays from the ring collection.
- Raises:
NotImplementedError – Always raised because multi-ring coordinate caching is not implemented.
- jp
- ip
- export_abaqus_for_meshing()[source]
Export the geometry in Abaqus mesh-input format.
- Raises:
NotImplementedError – Always raised because Abaqus export is not implemented.
- mesh()[source]
Generate a mesh for the ring collection.
- Raises:
NotImplementedError – Always raised because multi-ring meshing is not implemented.