Marching squares

xiaoxiao2021-02-28  71

  描述

Marching squares是计算机图形学中一个用于矩阵网格点数据生成等值面的一个算法。

       其主要思想是将每个2*2网格,其中4个顶点网格点根据等值线阈值处理为0,1标量。

   

1 代表数值大于阈值 0 代表数值小于阈值

这样处理之后有16中情况,2*2网格点根据左上角顺时针编号。

对于对角线这种情形,依据对角线大于两边处理。

算法主要流程:

      1. 遍历每个小网格,从16中固定情形中选择划线类别

      2.利用线性插值,结合网格点数值找寻交点

      3.  划线

代码

#coding:utf-8 from pylab import * from matplotlib.ticker import MultipleLocator, FormatStrFormatter class PlotDemo: def __init__(self,m,n): self._net = None self.m = m self.n = n def _set_default_figure(self,m,n): ax = subplot(111) #注意:一般都在ax中设置,不再plot中设置 #设置主刻度标签的位置,标签文本的格式 xmajorLocator = MultipleLocator(10) #将x主刻度标签设置为20的倍数 xmajorFormatter = FormatStrFormatter('%1.1f') #设置x轴标签文本的格式 xminorLocator = MultipleLocator(1) #将x轴次刻度标签设置为5的倍数 ymajorLocator = MultipleLocator(10) #将y轴主刻度标签设置为0.5的倍数 ymajorFormatter = FormatStrFormatter('%1.1f') #设置y轴标签文本的格式 yminorLocator = MultipleLocator(1) #将x轴次刻度标签设置为5的倍数 ax.set_xlim(0,m) ax.set_ylim(0,n) ax.xaxis.set_major_locator(xmajorLocator) ax.xaxis.set_major_formatter(xmajorFormatter) ax.yaxis.set_major_locator(ymajorLocator) ax.yaxis.set_major_formatter(ymajorFormatter) #显示次刻度标签的位置,没有标签文本 ax.xaxis.set_minor_locator(xminorLocator) ax.yaxis.set_minor_locator(yminorLocator) ax.xaxis.grid(True, which='minor') #x坐标轴的网格使用主刻度 ax.yaxis.grid(True, which='minor') #y坐标轴的网格使用次刻度 def show_source(self): self._set_default_figure(self.m, self.n) if self._net is None: raise Exception net = self._net.net_info shape = net.shape xlen = shape[0] ylen = shape[1] for i in range(xlen): for j in range(ylen): if net[i][j] > 0: plot(i,j,'g+') show() def show_contour(self): self._set_default_figure(self.m, self.n) net = self._net.net_info shape = net.shape xlen = shape[0] ylen = shape[1] for i in range(xlen): for j in range(ylen): if net[i][j] > 0: plot(i,j,'g+') net = self._net utils = MarchSquareUtlis(net) lines = utils.trancing_contours() width,height = net.net_info.shape arr = net.net_info idx = 0 for i in range(width-1): for j in range(height-1): x,y = i,j count,v1,v2,v3,v4,v5,v6,v7,v8 = lines[idx] idx = idx + 1 if count == 0: continue if count == 1: x1 = x + v1 y1 = y + v2 x2 = x + v3 y2 = y + v4 plot(x1,y1,x2,y2,'ro') if count == 2: x1 = x + v1 y1 = y + v2 x2 = x + v3 y2 = y + v4 plot(x1,y1,x2,y2,'ro') x1 = x + v5 y1 = y + v6 x2 = x + v7 y2 = y + v8 plot(x1,y1,x2,y2,'ro') show() def set_net_info(self, net_info): self._net = net_info class RandomGenNet(object): def __init__(self): self.arr = self._gen_random() def __init__(self,m,n): self.arr = self._gen_random(m,n) @property def net_info(self): return self.arr def _gen_random(self,m=100,n=100): return np.zeros((m,n),dtype='double') def add_circle(self,center_x, center_y, radius,val): r = int(radius + 0.5) for x in range(center_x - r, center_x + r): rx = np.abs(center_x - x) ry = int( np.sqrt(radius * radius - rx * rx)) for y in range(ry): self.arr[x][center_y - y] = val self.arr[x][center_y + y] = val return def add_retangle(self,lf_up_x, lf_up_y, width, height,val): for i in range(width): for j in range(height): self.arr[lf_up_x + i][lf_up_y + j] = val #clock-wise, top-left|top-right|bottom-right|bottom_left def get_retangle_bit(v1, v2, v3, v4): return v1 << 3 | v2 << 2 | v3 << 1 | v4 #shift relative to top-left def get_retangle_shift(bitval): if bitval == 0 or bitval == 15: return (0,None,None,None,None,None,None,None,None) if bitval == 1 or 14: return (1,0,0.5,0.5,1,None,None,None,None) if bitval == 2 or bitval == 13: return (1,0.5,1,1,0.5,None,None,None,None) if bitval == 3 or bitval == 12: return (1,0,0.5,1,0.5,None,None,None,None) if bitval == 4 or bitval == 11: return (1,0,0.5,1,0.5,None,None,None,None) if bitval == 5: return (2,0,0.5,0.5,0,0.5,1,1,0.5) if bitval == 6 or bitval == 9: return (1,0.5,0,0.5,1,None,None,None,None) if bitval == 7 or bit == 8: return (1,0,0.5,0.5,0,None,None,None,None) if bitval == 10: return (2,0,0.5,0.5,1,0.5,0,1,0.5) class MarchSquareUtlis(object): def __init__(self, net): self.net = net def trancing_contours(self): ret = [] width,height = self.net.net_info.shape arr = self.net.net_info for i in range(width-1): for j in range(height-1): v1 = int(arr[i][j]) v2 = int(arr[i + 1][j]) v3 = int(arr[i + 1][j + 1]) v4 = int(arr[i][j + 1]) bitv = get_retangle_bit(v1,v2,v3,v4) net_shift = get_retangle_shift(bitv) ret.append(net_shift) return ret demo = PlotDemo(100,100) netinfo = RandomGenNet(100,100) netinfo.add_circle(20,20,10,1) netinfo.add_circle(70,50,20,1) netinfo.add_retangle(20,45,40,20,1) netinfo.add_retangle(70,50,10,10,1) demo.set_net_info(netinfo) #demo.show_source() demo.show_contour() print get_retangle_bit(1,1,1,0) print range(3)

参考

Marching_squares_wiki
转载请注明原文地址: https://www.6miu.com/read-82906.html

最新回复(0)