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: object

Multi-straight-line (polyline) entity in 2D for UPXO.

A connected chain of Sline2d line 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:
  • llist (list of Sline2d) – Ordered line segments forming the polyline chain.

  • close (bool, optional) – If True, append a closing segment from the last node back to the first node.

Returns:

Assembled polyline.

Return type:

MSline2d

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:
  • nodes (list of Point2d) – Ordered nodes of the polyline.

  • close (bool, optional) – If True, append a closing segment.

Returns:

Assembled polyline.

Return type:

MSline2d

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:
  • coords (array-like of shape (n, 2)) – Ordered (x, y) coordinate pairs.

  • close (bool, optional) – If True, append a closing segment.

Returns:

Assembled polyline.

Return type:

MSline2d

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:
  • var_l (str, optional) – Length variation type (e.g., ‘constant’, ‘random’).

  • var_ang (str, optional) – Angle variation type (e.g., ‘constant’, ‘random’).

  • specs (dict, optional) – Specifications dict with keys: ‘n’ (count), ‘max_total_length’, ‘min_total_length’, ‘mean_length’.

Notes

To be developed.

property nlines

Return number of lines.

property centroid

Compute and return centroid of the polyline.

Returns:

Mean coordinate (x, y) of all nodes.

Return type:

numpy.ndarray

property centroid_p2dl

Return centroid as p2d_leanest point object.

Returns:

Lightweight point object at polyline centroid.

Return type:

p2d_leanest

property length

Return total length of all lines in polyline.

Returns:

Sum of all individual line lengths.

Return type:

float

property lengths

Return individual line lengths as list.

Returns:

Lengths of each line in the polyline.

Return type:

list

property nnodes

Return number of lines.

property coords

Get all node coordinates as 2D array.

Returns:

Array of shape (n_nodes, 2) with (x, y) coordinates.

Return type:

numpy.ndarray

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:

float

property gradients

Return gradient of every line.

property get_nodes

Return unique list of nodes in the multi-straight-line object.

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:

numpy.ndarray

property mid_nodes

Return midpoint nodes of all lines.

Returns:

Mid-point of each line segment in the polyline.

Return type:

list

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:
  • saa (bool, optional) – If True, modify self in place (save-and-apply). If False, operate on a deep copy.

  • throw (bool, optional) – If True, return the (possibly copied) result.

Returns:

Flipped polyline if throw is True, else None.

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 multisline2d must 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 multisline2d must 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:

tuple

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:

list

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.

Examples

unclose()[source]

Remove the closing line.

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:

int or list of int

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:
  • method (str, optional) – Method for splicing. Options include ‘points’ (default).

  • points (list, optional) – Points at which to splice.

  • perform_checks (bool, optional) – Whether to perform validation checks.

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.lines at a fractional position.

Parameters:
  • line_number (int, optional) – Index in self.lines to subdivide (zero-based).

  • f (float, optional) – Fractional position along the target line in (0, 1) where the split is made.

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.

Parameters:

tolerance (float, optional) – Maximum distance for considering points duplicates. Default: 1E-8.

Returns:

True if overlapping points found, False otherwise.

Return type:

bool

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.

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: object

Ring 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.

segments

Collection of MSline2d objects forming the ring.

Type:

list

segids

Segment identifiers.

Type:

list

segflips

Boolean flags indicating if segments were flipped for continuity.

Type:

list

nsegs

Number of segments in the ring.

Type:

int

closed

Whether ring is topologically closed.

Type:

bool

conn0

First-order connectivity status (start-end closure).

Type:

bool

conn1

Second-order connectivity status (inter-segment continuity).

Type:

dict

Notes

ring2d is in active development. Closure enforcement, reordering, and polygon generation are implemented; polygon meshing is not yet available.

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
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:

bool

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.

Returns:

  • closed (True, if closd or has been closed.)

  • last_seg_flipped (True, if seg was originally found open but closed.)

  • flip_possible (Whether flipped or not, if True, indicates that) – the segments can be closed between first and last ones.

connectivity1()[source]

Assess closure of all intermediate segments.

assess_segment_point_overlaps(line_check=False)[source]

Check all segments for duplicate/overlapping nodes.

Parameters:

line_check (bool, optional) – If True, also check for overlapping lines (not yet operational).

Returns:

Boolean list for each segment indicating overlap presence.

Return type:

list

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:

numpy.ndarray

property centroid

Compute centroid of the ring shape.

Returns:

Mean (x, y) coordinate of all ring nodes.

Return type:

numpy.ndarray

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:

numpy.ndarray

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:

numpy.ndarray

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:

float

property perimeter

Compute perimeter (boundary length) of ring.

Returns:

Total perimeter of ring polygon.

Return type:

float

property is_closed

Check if ring is topologically closed.

Returns:

True if ring forms a closed loop.

Return type:

bool

property nsegments

Return number of segments in ring.

Returns:

Count of constituent MSline2d segments.

Return type:

int

property ncoords

Return total number of nodes in ring.

Returns:

Count of unique coordinate nodes.

Return type:

int

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 (final result, whethwr all make a chain or not, irrespective) – of the need for flip.

  • flip_needed (True if any of the multisline2d in the list neede to be) – flipped to enure spatial continuity. The actual e,ements needing flips can be found in second element opf every subliest in i_precede_chain.

  • i_precede_chain (list of do_i_precede results for every i:i+1 pair)

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:

tuple

coords
closed
conn0
conn1
class upxo.geoEntities.mulsline2d.mulring2d(rings)[source]

Bases: object

rings
build_points_list()[source]

Build a flat list of all points from the ring collection. Not yet implemented.

set_coords()[source]

Set coordinate arrays from the ring collection. Not yet implemented.

jp
ip
export_abaqus_for_meshing()[source]

Export the geometry in Abaqus mesh-input format. Not yet implemented.

mesh()[source]

Generate a mesh for the ring collection. Not yet implemented.