Marching squares

  描述

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
  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值