首页 > 其他分享 >多边形填充-活动边表法

多边形填充-活动边表法

时间:2024-07-08 10:30:35浏览次数:12  
标签:count 多边形 填充 point polys next pcur pa 边表法

参考文档:
参考1:https://blog.csdn.net/u013044116/article/details/49737585
参考2:https://blog.csdn.net/keneyr/article/details/83747501

算法思想:
对多边形沿y轴从0开始遍历,建立边表NET。只记录顶点的x, dx, ymax。
根据NET构建活动边表AET(activate edge table)。射线与多边形的交点坐标为(x + △x, y + 1), △x是斜率的倒数(dx)。详解见 参考1

实现代码:

点击查看代码
# encoding=utf8
import math

import cv2
import numpy as np


class EdgeTable:
    def __init__(self, x, dx, ymax):
        self.x = x
        self.dx = dx
        self.ymax = ymax
        self.next = None


def fill_polys(polys):
    poly_x_max = float('-inf')
    poly_y_max = float('-inf')
    for poly in polys:
        poly_x_max = max(poly_x_max, poly[0])
        poly_y_max = max(poly_y_max, poly[1])

    poly_x_max += 1
    poly_y_max += 1
    point_count = len(polys)

    # build edge table
    net = [None for _ in range(poly_y_max)]
    for i in range(poly_y_max):
        for j in range(point_count):
            # 一个点跟前面的点形成线段 跟后边的点也形成线段
            if polys[j][1] == i:
                if polys[(j - 1 + point_count) % point_count][1] > polys[j][1]:
                    x_ = polys[j][0]
                    dx_ = (
                        polys[(j - 1 + point_count) % point_count][0] - polys[j][0]
                    ) / (polys[(j - 1 + point_count) % point_count][1] - polys[j][1])
                    ymax_ = polys[(j - 1 + point_count) % point_count][1]
                    pnt = EdgeTable(x_, dx_, ymax_)
                    pnt.next = net[i]
                    net[i] = pnt

                if polys[(j + 1 + point_count) % point_count][1] > polys[j][1]:
                    x_ = polys[j][0]
                    dx_ = (
                        polys[(j + 1 + point_count) % point_count][0] - polys[j][0]
                    ) / (polys[(j + 1 + point_count) % point_count][1] - polys[j][1])
                    ymax_ = polys[(j + 1 + point_count) % point_count][1]
                    pnt = EdgeTable(x_, dx_, ymax_)
                    pnt.next = net[i]
                    net[i] = pnt

    # build activate edge table
    bg = np.zeros((poly_x_max, poly_y_max), dtype=np.uint8)
    aet = EdgeTable(0, 0, 0)
    for i in range(poly_y_max):
        # 计算新的交点 更新aet表
        pa = aet.next
        while pa:
            pa.x = pa.x + pa.dx
            pa = pa.next

        # 更新aet表之后对ate表进行排序
        # 断表排序 不开辟新空间
        pa = aet
        pcur = aet.next
        pa.next = None
        while pcur:
            while pa.next and pcur.x >= pa.next.x:
                pa = pa.next
            pt = pcur.next
            pcur.next = pa.next
            pa.next = pcur
            pcur = pt
            pa = aet

        # net表中的点加入到aet表中,并用插值法按x排序插入
        pn = net[i]
        pa = aet
        while pn:
            while pa.next and pn.x >= pa.next.x:
                pa = pa.next
            pt = pn.next
            pn.next = pa.next
            pa.next = pn
            pn = pt
            pa = aet

        # 填充
        pcur = aet.next
        while pcur and pcur.next:
            # 浮点数转成整数 如果dx是负数 向下取整;如果dx是正数 向上取整
            s = math.ceil(pcur.x) if pcur.dx > 0 else math.floor(pcur.x)
            e = math.ceil(pcur.next.x) if pcur.next.dx > 0 else math.floor(pcur.next.x)
            # for x in range(pcur.x, pcur.next.x+1):
            for x in range(s, e + 1):
                bg[x][i] = 1
            pcur = pcur.next

        # 从aet表中删除ymax==i的结点
        pa = aet
        pcur = pa.next
        while pcur:
            if pcur.ymax == i:
                pa.next = pcur.next
                del pcur
                pcur = pa.next
            else:
                pcur = pcur.next
                pa = pa.next

    print(bg)


def matrix(polys):
    m = np.zeros((10, 10), dtype=np.uint8)
    for x, y in polys:
        m[x, y] = 1
    return m


def cv_fill(polys):
    mask = np.zeros((5, 5), dtype=np.uint8)
    cv2.fillPoly(mask, [np.array(polys)], 1, lineType=cv2.FILLED)
    return mask


if __name__ == "__main__":
    # r = matrix([[8, 8], [2, 7], [5, 5], [2, 2], [5, 1], [9, 3]])
    # print(r)
    polys = [[2, 4], [1, 2], [3, 0], [4, 1], [3, 2], [4, 3]]
    fill_polys(polys)
    # cv_fill(polys)

结果展示:
image

标签:count,多边形,填充,point,polys,next,pcur,pa,边表法
From: https://www.cnblogs.com/yimeimanong/p/18289424

相关文章

  • MyBatis-Plus-实用的功能自动填充字段
    前言:java项目用到了mybatis-plus,在一些类里面需要在更新时候,统一设置,修改人,修改ID,修改时间。新增时候设置创建人,创建时间等基础类:@DatapublicabstractclassBaseModelimplementsSerializable{/***逻辑删除*/@TableField(value="is_delete",......
  • 正多边形内点黄金分割冒险游戏
    1.题目:正多边形内点的冒险游戏内容描述:选定五边形(P1,P2,...,P5)内的一个任意点P0。从P0出发,到任意顶点距离的0.618的点P0’(黄金分割点),给该P0’点着色。从P0’点出发,重复第2步,求得新的黄金分割点并着色。以上重复N次,比如,30000次问题:最后所有黄金分割点形成......
  • Asp .Net Core 系列:基于 Castle DynamicProxy + Autofac 实践 AOP 以及实现事务、用户
    目录什么是AOP?.NetCore中有哪些AOP框架?基于CastleDynamicProxy实现AOPIOC中使用CastleDynamicProxy实现事务管理实现用户自动填充什么是AOP?AOP(Aspect-OrientedProgramming,面向切面编程)是一种编程范式,旨在通过将横切关注点(cross-cuttingconcerns)从主要业务逻辑......
  • CesiumJS【Basic】- #053 绘制渐变填充多边形(Entity方式)-使用canvas
    文章目录绘制渐变填充多边形(Entity方式)-使用canvas1目标2代码2.1main.ts绘制渐变填充多边形(Entity方式)-使用canvas1目标使用Entity方式绘制绘制渐变填充多边形-使用canvas2代码2.1main.tsimport*asCesiumfrom'cesium';constviewer......
  • CesiumJS【Basic】- #054 绘制渐变填充多边形(Entity方式)-使用shader
    文章目录绘制渐变填充多边形(Entity方式)-使用shader1目标2代码2.1main.ts绘制渐变填充多边形(Entity方式)-使用shader1目标使用Entity方式绘制绘制渐变填充多边形-使用shader2代码2.1main.tsimport*asCesiumfrom'cesium';constviewer......
  • EasyExcel 填充+写入
    使用EasyExcel导出Excel时,有时会遇到如下情况:既要根据模板填充某些sheet又要根据业务写入某些sheetEasyExcel官方没有提供这样的示例,经过自己的研究和实验,得到了如下步骤:定义导出文件名StringfileName="测试.xlsx";获取模板文件InputStreamtemplateFile......
  • String.format 日期占位 去除左侧的填充0
    原文链接: https://baijiahao.baidu.com/s?id=1764834107971798887&wfr=spider&for=pc假设我们要输出当前的日期时间,我们可以使用如下代码:Datedate=newDate();System.out.println("输出结果:"+String.format("%tF%tT",date,date));输出结果为:输出结果:2023-......
  • 把采集的PCM音频数据填充到AVFrame中
    目录1.AVFrame结构体中部分音频参数说明2.和实际录音时音频属性的对应关系1.AVFrame结构体中部分音频参数说明typedefstructAVFrame{#defineAV_NUM_DATA_POINTERS8uint8_t*data[AV_NUM_DATA_POINTERS];//指向音频数据的指针数组intlinesize[AV_NUM_DATA_POI......
  • MyBatis-利用切面实现公有字段自动填充(非MyBatisPlus方式)
    需求:在MyBatis框架中,如何对createBy,createTime,updateBy等这些公有字段实现自动填充呢?网上搜了很多,实现的方案全是采用集成MyBatisPlus,利用其封装好的方法来实现的。。。。。数据准备:1、准备一张数据库表CREATETABLE`user`(`id`varchar(36)NOTNULL,`username`......
  • 【鸿蒙学习笔记】基础组件Blank:空白填充组件
    Blank:空白填充组件Column({space:20}){Row(){Text('Bluetooth')Blank().color(Color.Yellow)Toggle({type:ToggleType.Switch}).margin({top:14,bottom:14,left:6,right:6})}.backgroundColor(Color.Pink).borderRadius(15).padd......