【Grasshopper】【Python】点集排序:带索引的Z字形排序算法

Grasshopper Python点集排序:带索引的Z字形排序算法

1. 功能介绍

这段代码实现了一个在Grasshopper中的点集排序功能,不仅可以将空间中的点按照Y坐标分组并在每组内按X坐标排序,还能追踪每个点的原始索引位置。

2. 输入输出参数

  • 输入参数:
  • x: 待排序的点集(Point List)
  • t: 容差值(Number),默认2000
  • 输出参数:
  • a: 排序后的点集(Point List)
  • i: 排序后点的原始索引(Number List)
  • 3. 核心算法流程

    输入点集

    点集是否为空?

    创建点索引对

    返回None

    按Y坐标分组

    组内按X排序

    提取排序后的点

    提取对应的索引

    输出排序点集

    输出索引列表

    4. 代码解析

    4.1 点索引对的创建和处理

    points_with_index = list(enumerate(x))
    
  • 使用enumerate()创建(索引, 点)对
  • 将每个点与其原始位置绑定
  • 4.2 分组函数

    def groupPointsByY(points_with_index, tolerance):
        points_with_index = sorted(points_with_index, key=lambda pair: pair[1].Y)
        groups = []
        current_group = [points_with_index[0]]
        current_y = points_with_index[0][1].Y
    
  • 函数接收点索引对和容差值
  • 使用lambda函数访问点的Y坐标进行排序
  • pair[1]访问点对象,pair[0]访问索引
  • 4.3 分组逻辑

    for p in points_with_index[1:]:
        if abs(p[1].Y - current_y) <= tolerance:
            current_group.append(p)
        else:
            groups.append(current_group)
            current_group = [p]
            current_y = p[1].Y
    
  • 遍历点索引对
  • 基于Y坐标差值分组
  • 保持索引与点的关联
  • 4.4 排序和结果提取

    for group in grouped_points:
        group_sorted = sorted(group, key=lambda pair: pair[1].X)
        for index, point in group_sorted:
            sorted_points.append(point)
            sorted_indices.append(index)
    
  • 组内按X坐标排序
  • 分别提取点和索引
  • 维护排序后的两个列表
  • 5. Python语法要点

    5.1 元组拆包

    for index, point in group_sorted:
    
  • 直接将元组拆分为两个变量
  • 简化数据访问
  • 5.2 Lambda表达式

    key=lambda pair: pair[1].X
    
  • 用于定义排序键函数
  • 访问元组中点对象的坐标
  • 5.3 列表操作

    sorted_points.append(point)
    sorted_indices.append(index)
    
  • 使用append()逐个添加元素
  • 维护两个平行列表
  • 6. 数据结构

    6.1 点索引对

    (index, point) 结构:
    - index: 原始位置
    - point: 点对象
      - X: X坐标
      - Y: Y坐标
      - Z: Z坐标
    

    6.2 分组结构

    groups = [
        [(index1, point1), (index2, point2), ...],  # 第一组
        [(index3, point3), (index4, point4), ...],  # 第二组
        ...
    ]
    

    左上角向右上角排序↗

    # GH Python Component的设置:
    # x: 输入点集(point list)
    # t: 输入容差值(number),默认值可设为2000
    # a: 输出排序后的点集(point list)
    # i: 输出排序后点的原始索引(number list)
    
    def groupPointsByY(points_with_index, tolerance):
        """将Y坐标相近的点分组"""
        if not points_with_index:
            return []
        
        # 按Y坐标排序,注意points_with_index中的每个元素是(index, point)的元组
        points_with_index = sorted(points_with_index, key=lambda pair: pair[1].Y)
        groups = []
        current_group = [points_with_index[0]]
        current_y = points_with_index[0][1].Y  # 使用pair[1]访问点
        
        # 遍历所有点,根据Y坐标差值分组
        for p in points_with_index[1:]:
            if abs(p[1].Y - current_y) <= tolerance:  # 使用pair[1]访问点
                current_group.append(p)
            else:
                groups.append(current_group)
                current_group = [p]
                current_y = p[1].Y  # 使用pair[1]访问点
        
        groups.append(current_group)
        return groups
    
    if x:  # 确保输入不为空
        # 设置默认容差值
        tolerance = t if t is not None else 2000
        
        # 创建带索引的点列表
        points_with_index = list(enumerate(x))  # 创建(索引, 点)对的列表
        
        # 将点按Y坐标分组
        grouped_points = groupPointsByY(points_with_index, tolerance)
        
        # 对每组内的点按X坐标排序
        sorted_points = []
        sorted_indices = []
        for group in grouped_points:
            # 按X坐标排序,同时保持索引
            group_sorted = sorted(group, key=lambda pair: pair[1].X)  # 使用pair[1]访问点
            
            # 分离点和索引
            for index, point in group_sorted:
                sorted_points.append(point)
                sorted_indices.append(index)
        
        a = sorted_points
        i = sorted_indices
    else:
        a = None
        i = None
    

    左上角向右下角排序↘

    # GH Python Component的设置:
    # x: 输入点集 (point list)
    # t: 输入容差值 (number),默认值可设为2000
    # a: 输出排序后的点集 (point list)
    # i: 输出排序后点的原始索引 (number list)
    
    def groupPointsByY(points_with_index, tolerance):
        """将Y坐标相近的点分组,并按Y值从大到小排序,确保按从上到下进行分组"""
        if not points_with_index:
            return []
        
        # 修改:按Y坐标从大到小排序(最高的点在前),reverse=True
        points_with_index = sorted(points_with_index, key=lambda pair: pair[1].Y, reverse=True)
        groups = []
        current_group = [points_with_index[0]]
        current_y = points_with_index[0][1].Y  # 当前组参考的Y值
        
        # 遍历剩余的点,若两点Y坐标差值在容差范围内,则归为一组
        for p in points_with_index[1:]:
            if abs(p[1].Y - current_y) <= tolerance:
                current_group.append(p)
            else:
                groups.append(current_group)
                current_group = [p]
                current_y = p[1].Y
        groups.append(current_group)
        return groups
    
    if x:  # 确保输入不为空
        # 设置默认容差值
        tolerance = t if t is not None else 2000
        
        # 为每个点创建一个(原始索引, 点)的元组列表
        points_with_index = list(enumerate(x))
        
        # 按Y坐标(从上到下)分组
        grouped_points = groupPointsByY(points_with_index, tolerance)
        
        sorted_points = []
        sorted_indices = []
        # 对每组内的点按X坐标从小到大排序(从左至右)
        for group in grouped_points:
            group_sorted = sorted(group, key=lambda pair: pair[1].X)
            for index, point in group_sorted:
                sorted_points.append(point)
                sorted_indices.append(index)
        
        a = sorted_points
        i = sorted_indices
    else:
        a = None
        i = None
    

    作者:hmywillstronger

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【Grasshopper】【Python】点集排序:带索引的Z字形排序算法

    发表回复