[Python] Generating a Line Along a Triangular Solid Using Vertex Points and Neighbors

Discussão em 'Python' iniciado por Stack, Maio 26, 2025.

  1. Stack

    Stack Membro Participativo

    How to generate a line along a triangular solid using vertex points and neighbors?

    I have a solid composed of triangles, each defined by a triangle ID, three vertices (vertex1, vertex2, vertex3), and three neighboring triangles (n1, n2, n3). The data is structured as a list: [Tid, v1, v2, v3, n1, n2, n3]. n1, n2, n3 - it is neighboring points number. Below are examples of this data. Additionally, I have the coordinates of the points in the form (x, y, z). The numbers (Id number - Tid) of the triangles may not match the direction of the solid. This data is also provided below.

    How to do it correctly? How to generate a line along a triangular solid? The shape of the solid can be different. See the picture.

    Examples of the triangle and neighbor data (Tid, v1, v2, v3, n1, n2, n3):

    1, 1, 78, 79, 151, 152, 2,
    2, 1, 79, 80, 1, 153, 3,
    3, 1, 80, 2, 2, 4, 226,
    4, 2, 80, 81, 3, 157, 5,
    5, 2, 81, 3, 4, 6, 230,
    6, 3, 81, 82, 5, 158, 7,


    Examples of the point coordinates (point number, x, y, z):

    1, 21686.416, 11496.370, 1081.922,
    2, 21687.582, 11498.463, 1067.326,
    3, 21687.582, 11498.463, 1082.489,
    4, 21684.070, 11500.333, 1078.825,
    5, 21681.135, 11499.179, 1076.579,
    6, 21674.309, 11505.523, 1066.694,


    Examples picture 1. In the picture you can see that the solid consists of the triangles [​IMG]

    Examples picture 2. Inthe picture you can see that the solid consists of the triangles [​IMG]

    def compute_centroid(v1, v2, v3):
    return [(v1 + v2 + v3) / 3.0 for i in range(3)]

    # 2. Build a graph of triangle neighbors
    # Treat each triangle as a node, and connect it to its neighbors.

    from collections import defaultdict

    import numpy as np

    def read_vertices(file_path):
    """Parse point data into a dictionary with incremental numbering"""
    points = {}
    count = 0 # This will be our incremental counter
    with open(file_path, 'r') as point_lines:
    for line in point_lines:
    if not line.strip():
    continue
    parts = [p.strip() for p in line.strip().split(',') if p.strip()]
    first_index = parts[0]
    # Skip lines that don't have at least 4 values (x, y, z needed)
    if len(parts) < 4:
    continue
    try:
    if first_index.lstrip('-').isdigit() and int(first_index) != 0:
    # Ignore the original point ID (parts[0]) and use our counter instead
    # coords = [float(x) for x in parts[1:4]] # Only get x,y,z coordinates
    count += 1 # Increment our counter
    # points[count] = np.array(coords) # Use count as the key
    x = float(parts[1].strip())
    y = float(parts[2].strip())
    z = float(parts[3].strip())
    points[count] = (x, y, z)

    except (ValueError, IndexError):
    continue # Skip lines with invalid format
    return points


    def read_triangles(file_path):
    triangle_data = []
    with open(file_path, 'r') as file:
    for line in file:
    # line = line[0]
    parts = line.strip().split(',')
    # print(len(parts), "===",parts)
    # print(parts)
    if len(parts) >= 7:
    first_index = parts[0].strip()
    if first_index.lstrip('-').isdigit() and int(first_index) != 0:
    Tid = int(parts[0].strip())
    v1 = int(parts[1].strip())
    v2 = int(parts[2].strip())
    v3 = int(parts[3].strip())
    n1 = int(parts[4].strip())
    n2 = int(parts[5].strip())
    n3 = int(parts[6].strip())
    triangle_data.append([Tid, v1, v2, v3, n1, n2, n3])
    return triangle_data

    def create_strfile(file_path, dataxyz):
    with open(file_path, "w") as fstr:
    fstr.write(",,,\n")
    fstr.write("0,0.000,0.000,0.000,0.000,0.000,0.000\n")
    for linexyz in dataxyz:
    x, y, z = linexyz
    fstr.write(f"5, {x:10.3f}, {y:10.3f}, {z:5.3f}, \n")
    fstr.write("0,0.000,0.000,0.000,\n")
    fstr.write("0,0.000,0.000,0.000,END\n")

    dtm_file_path = f'E:\\{filname}.dtm'
    str_file_path = f'E:\\{filname}.str'
    str_center_line = f'E:\\{filname}_center.str'
    point_data = read_vertices(str_file_path)
    triangle_data = read_triangles(dtm_file_path)

    print("Point Data Example:", len(point_data),"==",list(point_data.items())[:3])
    print("Triangle Data Example:", triangle_data[:3])


    class Triangle:
    def __init__(self, tid, v1, v2, v3, n1, n2, n3):
    self.id = tid
    self.vertices = [v1, v2, v3]
    self.neighbors = [n1, n2, n3]

    class Point:
    def __init__(self, pid, x, y, z):
    self.id = pid
    self.coords = (x, y, z)

    # triangle_list = triangle_data
    # point_list = point_data

    # triangle_list = [Triangle(t[0], t[1], t[2], t[3], t[4], t[5], t[6]) for t in triangle_data]
    triangle_list = [Triangle(t[0], t[1], t[2], t[3], t[4], t[5], t[6]) for t in triangle_data if all(v in point_data for v in [t[1], t[2], t[3]])]

    point_list = [Point(pid, *coords) for pid, coords in point_data.items()]

    triangles = {t.id: t for t in triangle_list}
    points = {p.id: p for p in point_list}
    print("points==",len(points), "point_list=",len(point_list) )
    # # Build maps
    # triangles = {t.id: t for t in triangle_list}
    # points = {p.id: p for p in point_list}

    # Build edge map
    from collections import defaultdict
    edges = defaultdict(list)
    for t in triangles.values():
    verts = t.vertices
    for i in range(3):
    edge = tuple(sorted((verts, verts[(i+1)%3])))
    edges[edge].append(t.id)

    # Walk along mesh
    visited = set()
    path = []
    def walk(tid=1, last_edge=None):
    if tid in visited:
    return
    visited.add(tid)
    t = triangles[tid]
    for i in range(3):
    n_tid = t.neighbors
    if n_tid and n_tid not in visited:
    edge = tuple(sorted((t.vertices, t.vertices[(i+1)%3])))
    path.append(edge)
    walk(n_tid, edge)

    walk(1)

    # print(path)

    lines = []
    for v1, v2 in path:
    print(v1, v2)
    p1 = points[v1].coords
    p2 = points[v2].coords
    lines.append((p1, p2))


    # print(lines)

    # Convert line segments into ordered list of unique points
    path_points = []
    seen = set()

    for p1, p2 in lines:
    if p1 not in seen:
    path_points.append(p1)
    seen.add(p1)
    if p2 not in seen:
    path_points.append(p2)
    seen.add(p2)

    # Now write to .str file
    create_strfile(str_center_line, path_points)


    I tried different ways but not successful. :(

    Continue reading...

Compartilhe esta Página