[从头学数学] 第283节 [计算几何] 多边形的单调块划分
2016-09-28 16:11
435 查看
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年09月28日 15:47:30, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201609/26b96749627479e5bb9a916f6134515c)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201609/3874d61bb2b9418cf184df53d093da5b)
<span style="font-size:18px;">#
>>>
[[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [8, 3], [6, 9]]
[1.33, 3] End
[2, 3] Regular
[8, 3] End
[0.8, 3.8] Regular
[6, 3.86] Regular
[3.33, 5] Split
S
up
[Point([2.4, 5.4]), Point([0.8, 3.8]), Point([1.33, 3]), Point([2, 3]), Point([3.33, 5])]
[1.33, 3] End
[2, 3] Regular
[0.8, 3.8] Regular
[3.33, 5] Regular
[2.4, 5.4] Start
[Point([3.33, 5]), Point([6, 3.86]), Point([8, 3]), Point([6, 9]), Point([2.4, 5.4])]
[8, 3] End
[6, 3.86] Regular
[3.33, 5] Regular
[2.4, 5.4] Regular
[6, 9] Start
---
2
[[[2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [2.4, 5.4]], [[3.33, 5], [6, 3.86], [8, 3], [6, 9], [2.4, 5.4], [3.33, 5]]]
def tmp6():
path = [[[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.5, 1.5], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [-6, 9], [-0.37, 2.56], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [1.78, 2.33], [3.67, -0.5], [4.29, 0.43], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.29, 0.43], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.56, -3.33], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [5.35, -3.97], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [4, -1], [6, -3], [8, -7], [8, 3], [6, 9]]]
len_path = len(path);
#第几条线段作为测试
n = 1;
pathArray = [];
dealed = [];
pathArray.append(path
);
while (len(pathArray) > 0):
path_ = pathArray.pop(0);
print(path_);
#把路径注册给Polygon类
poly = Polygon(path_);
poly.genVertexTree();
#计算凹凸性,这步不能省,否则结果会出错。
poly.setConcave();
#把路径注册给Path类
a = Path(path_);
#标记路径中是否有需要处理的点
changed = False;
for item in poly.vertexTree:
#print(item);
stype = item.pointType();
print(item.point, stype);
pitem = item.point;
#如果顶点类型是汇合顶点
if (stype == 'Merge'):
print('M');
downBrother = a.findDownBrother(pitem);
if (downBrother != None): #这个其实可以保证,这是由Merge顶点的特性决定的。
print('down');
#找到两个顶点在路径中的序号
idx1 = a.path.index(pitem);
idx2 = a.path.index(downBrother);
pathArray.append(a.majorSubpath(idx1, idx2));
pathArray.append(a.minorSubpath(idx1, idx2));
changed = True;
break;
elif (stype == 'Split'):
print('S');
upBrother = a.findUpBrother(pitem);
if (upBrother != None): #这个其实可以保证,这是由Merge顶点的特性决定的。
print('up');
#找到两个顶点在路径中的序号
idx1 = a.path.index(pitem);
idx2 = a.path.index(upBrother);
pathArray.append(a.majorSubpath(idx1, idx2));
pathArray.append(a.minorSubpath(idx1, idx2));
changed = True;
break;
if (changed == False):
dealed.append(path_);
print('---');
print(len(dealed));
print(dealed);
#</span>
![](https://oscdn.geek-share.com/Uploads/Images/Content/201609/3ee04ea0d948a3a6a1beb1da7d75761e)
$split = [[[2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [2.4, 5.4]], [[3.33, 5], [6, 3.86], [8, 3], [6, 9], [2.4, 5.4], [3.33, 5]]]
<span style="font-size:18px;">//
if (1) {
var r = 20;
config.setSector(1,1,1,1);
config.graphPaper2D(0, 0, r);
config.axis2D(0, 0, 250, 1.2);
//坐标轴设定
var scaleX = 2*r, scaleY = 2*r;
var spaceX = 2, spaceY = 2;
var xS = -10, xE = 10;
var yS = -10, yE = 10;
config.axisSpacing(xS, xE, spaceX, scaleX, 'X');
config.axisSpacing(yS, yE, spaceY, scaleY, 'Y');
var transform = new Transform();
//顶点
var a = [];
for (var i = 0; i < $vertex.length; i++) {
a.push($vertex[i][0]);
}
//显示变换
if (a.length > 0) {
a = transform.scale(transform.translate(a, 0, 0), scaleX/spaceX, scaleY/spaceY);
}
var lable = [];
for (var i = 0; i < 100; i++) {
lable.push(i.toFixed(0));
}
/*
//边集
var b = [];
for (var i = 0; i < $seg.length; i++) {
b.push([a[$seg[i][0]], a[$seg[i][1]]]);
}
var edges = b.length;
for (var i = 0; i < edges; i++) {
shape.multiLineDraw([].concat(b[i]), 'red');
}*/
var colorArray = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple'];
var seg = [];
var idx = xGlobal;
var len = $path2.length;
plot.setLineWidth(3);
seg = transform.scale(transform.translate($path2[idx%len], 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.multiLineDraw([].concat(seg), 'pink');
plot.fillText('路径: '+(idx%len).toFixed(0), 200, -150, 200);
for (var i = 0; i < $split.length; i++) {
seg = transform.scale(transform.translate($split[i], 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.multiLineDraw([].concat(seg), colorArray[i%7]);
}
//主要顶点
shape.pointDraw([].concat(a), 'blue', 1, 1, lable);
cPoint = transform.scale(transform.translate($center, 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.pointDraw([].concat([cPoint[idx%len]]), 'black');
/*
concavePoint = transform.scale(transform.translate($concave[idx%len], 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.pointDraw([].concat(concavePoint), 'orange');
*/
//次要顶点
var b = [];
for (var i = 0; i < 6; i++) {
b = [].concat($pointType[idx%len][i]);
//显示变换
if (b.length > 0) {
b = transform.scale(transform.translate(b, 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.pointDraw([].concat(b), colorArray[(i-1)%7]);
}
}
}
//</span>
更多图片:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201609/96ff9196b13e285a81888c72c020d08e)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201609/5ffc1580d9262d10e7f88ea744dc5d95)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201609/6ac655997f89c6ebedda9a9cd5e25297)
本节到此结束,欲知后事如何,请看下回分解。
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年09月28日 15:47:30, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。
<span style="font-size:18px;">#
>>>
[[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [8, 3], [6, 9]]
[1.33, 3] End
[2, 3] Regular
[8, 3] End
[0.8, 3.8] Regular
[6, 3.86] Regular
[3.33, 5] Split
S
up
[Point([2.4, 5.4]), Point([0.8, 3.8]), Point([1.33, 3]), Point([2, 3]), Point([3.33, 5])]
[1.33, 3] End
[2, 3] Regular
[0.8, 3.8] Regular
[3.33, 5] Regular
[2.4, 5.4] Start
[Point([3.33, 5]), Point([6, 3.86]), Point([8, 3]), Point([6, 9]), Point([2.4, 5.4])]
[8, 3] End
[6, 3.86] Regular
[3.33, 5] Regular
[2.4, 5.4] Regular
[6, 9] Start
---
2
[[[2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [2.4, 5.4]], [[3.33, 5], [6, 3.86], [8, 3], [6, 9], [2.4, 5.4], [3.33, 5]]]
def tmp6():
path = [[[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.5, 1.5], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [-6, 9], [-0.37, 2.56], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [1.78, 2.33], [3.67, -0.5], [4.29, 0.43], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.29, 0.43], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.56, -3.33], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [5.35, -3.97], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [4, -1], [6, -3], [8, -7], [8, 3], [6, 9]]]
len_path = len(path);
#第几条线段作为测试
n = 1;
pathArray = [];
dealed = [];
pathArray.append(path
);
while (len(pathArray) > 0):
path_ = pathArray.pop(0);
print(path_);
#把路径注册给Polygon类
poly = Polygon(path_);
poly.genVertexTree();
#计算凹凸性,这步不能省,否则结果会出错。
poly.setConcave();
#把路径注册给Path类
a = Path(path_);
#标记路径中是否有需要处理的点
changed = False;
for item in poly.vertexTree:
#print(item);
stype = item.pointType();
print(item.point, stype);
pitem = item.point;
#如果顶点类型是汇合顶点
if (stype == 'Merge'):
print('M');
downBrother = a.findDownBrother(pitem);
if (downBrother != None): #这个其实可以保证,这是由Merge顶点的特性决定的。
print('down');
#找到两个顶点在路径中的序号
idx1 = a.path.index(pitem);
idx2 = a.path.index(downBrother);
pathArray.append(a.majorSubpath(idx1, idx2));
pathArray.append(a.minorSubpath(idx1, idx2));
changed = True;
break;
elif (stype == 'Split'):
print('S');
upBrother = a.findUpBrother(pitem);
if (upBrother != None): #这个其实可以保证,这是由Merge顶点的特性决定的。
print('up');
#找到两个顶点在路径中的序号
idx1 = a.path.index(pitem);
idx2 = a.path.index(upBrother);
pathArray.append(a.majorSubpath(idx1, idx2));
pathArray.append(a.minorSubpath(idx1, idx2));
changed = True;
break;
if (changed == False):
dealed.append(path_);
print('---');
print(len(dealed));
print(dealed);
#</span>
<span style="font-size:18px;"># class Path(): def info(self): print(self.path); def __init__(self, path): if (path[-1] == path[0]): path = path[:-1]; if (type(path[0]) == Point): self.path = path; else: self.path = []; for i in range(len(path)): self.path.append(Point(path[i])); #判断路径相等 def __eq__(self, other): if other == None: return False; len_1 = len(self.path); len_2 = len(other.path); if (len_1 != len_2): return False; if (other[0] in self): idx = self.path.index(other[0]); for i in range(len_1): if other[i] != self.path[(idx+i)%len_1]: return False; return True; else: return False; def __len__(self): return len(self.path); def __iter__(self): for i in range(len(self)): yield self.path[i]; def __contains__(self, item): return item in self.path; def __getitem__(self, index): return self.path[index]; #路径上的顶点集 def pointSet(self): pSet = set(); for i in range(len(self.path)): pSet.add(self.path[i]); return pSet; #两个点序号之间的劣弧路径,是以通过点的数量定优劣弧的,不是根据路径长度。 def minorSubpath(self, idx1, idx2): idx1, idx2 = idx1%len(self), idx2%len(self); idx1, idx2 = min(idx1, idx2), max(idx1, idx2); len_path = len(self.path); if (idx2 - idx1) < len_path//2: subPath = self.path[idx1:idx2+1]; else: subPath = self.path[idx2:]+self.path[:idx1+1]; return subPath; #两个点序号之间的优弧路径,是以通过点的数量定优劣弧的,不是根据路径长度。 def majorSubpath(self, idx1, idx2): idx1, idx2 = idx1%len(self), idx2%len(self); idx1, idx2 = min(idx1, idx2), max(idx1, idx2); len_path = len(self.path); if (idx2 - idx1) >= len_path//2: subPath = self.path[idx1:idx2+1]; else: subPath = self.path[idx2:]+self.path[:idx1+1]; return subPath; #连接两段子路径,两段路径必须有相同的起点和终点,这样形成一个环路 def linkPath(self, path1, path2): result = []; if path1[0] == path2[0] and path1[-1] == path2[-1]: path2 = list(reversed(path2)); result = path1[:-1]+path2[:-1]; elif path1[0] == path2[-1] and path1[-1] == path2[0]: result = path1[:-1]+path2[:-1]; return result; #在路径中两个不同点增加对角线,把一条路径分割成两条路径 def addDiagonal(self, index1, index2): if (abs(index1 - index2) > 1): return [self.minorSubpath(index1, index2), self.majorSubpath(index1, index2)]; #找某点的左邻居边,也就是路径中处于给定点的左边,并且在y扫描线上最接近的那条边 def findLeftNearestEdge(self, point): edge = None; scanPoint = None; len_ = len(self.path); for i in range(len_): seg = SegLine(self.path[i].value(), self.path[(i+1)%len_].value()); #点在边的右侧 if (judgePointAgainstEdgePosition(seg, point) == 'Right'): if (edge == None): edge = seg; scanPoint = calcScanLineCrosspoint(seg, point); else: a = calcScanLineCrosspoint(seg, point); #取扫描线的交点的x值 if a[0] > scanPoint[0]: edge = seg; scanPoint = a; return [edge, scanPoint]; #找某点的右邻居边,也就是路径中处于给定点的右边,并且在y扫描线上最接近的那条边 def findRightNearestEdge(self, point): edge = None; scanPoint = None; len_ = len(self.path); for i in range(len_): seg = SegLine(self.path[i].value(), self.path[(i+1)%len_].value()); #点在边的左侧 if (judgePointAgainstEdgePosition(seg, point) == 'Left'): if (edge == None): edge = seg; scanPoint = calcScanLineCrosspoint(seg, point); else: a = calcScanLineCrosspoint(seg, point); #取扫描线的交点的x值 if a[0] < scanPoint[0]: edge = seg; scanPoint = a; return [edge, scanPoint]; #找某点的上兄弟点,这个点的y坐标大于给定点, #并且处于该点的左、右邻居边之间。 #如果没有这种点,返回左、右邻居边的上顶点中y值比较小的那一个点。 def findUpBrother(self, point): #point是Point类型 rEdge = self.findRightNearestEdge(point); lEdge = self.findLeftNearestEdge(point); rSeg, lSeg = rEdge[0], lEdge[0]; upBrother = None; if (rSeg != None and lSeg != None): len_ = len(self.path); for i in range(len_): a = self.path[i].value(); b = point.value(); if (a[1] > b[1]): if (judgePointAgainstEdgePosition(rSeg, self.path[i]) == 'Left' and\ judgePointAgainstEdgePosition(lSeg, self.path[i]) == 'Right'): if upBrother == None: upBrother = self.path[i]; else: if (upBrother < self.path[i]): upBrother = self.path[i]; if upBrother == None: upBrother = min(Point(lSeg.value()[1]), Point(rSeg.value()[1])); return upBrother; #找某点的下兄弟点,这个点的y坐标小于给定点, #并且处于该点的左、右邻居边之间。 #如果没有这种点,返回左、右邻居边的下顶点中y值比较大的那一个点。 def findDownBrother(self, point): #point是Point类型 rEdge = self.findRightNearestEdge(point); lEdge = self.findLeftNearestEdge(point); rSeg, lSeg = rEdge[0], lEdge[0]; downBrother = None; if (rSeg != None and lSeg != None): len_ = len(self.path); for i in range(len_): a = self.path[i].value(); b = point.value(); if (a[1] < b[1]): if (judgePointAgainstEdgePosition(rSeg, self.path[i]) == 'Left' and\ judgePointAgainstEdgePosition(lSeg, self.path[i]) == 'Right'): if downBrother == None: downBrother = self.path[i]; else: if (downBrother < self.path[i]): downBrother = self.path[i]; if downBrother == None: downBrother = max(Point(lSeg.value()[0]), Point(rSeg.value()[0])); return downBrother; #三个点的叉积 def crossProduct(P1, P2, P3): x1, y1, x2, y2, x3, y3 = P1[0], P1[1], P2[0], P2[1], P3[0], P3[1]; # # 1 1 1 # x_1 x_2 x_3 # y_1 y_2 y_3 # #逆时针结果为正,顺时针为负 return round((x1*y2-x2*y1)-(x1*y3-x3*y1)+(x2*y3-x3*y2), 3); #判断点在边的左边还是右边 def judgePointAgainstEdgePosition(seg, point): #传入SegLine类型和Point类型,这样方便比较 #SegLine是以y优先x其次由小大大排序的,终端点按排序规则大于起始端点 pValue = point.value(); sValue = seg.value(); x0, y0, x1, y1, x2, y2 = pValue[0], pValue[1], sValue[0][0], sValue[0][1],\ sValue[1][0], sValue[1][1]; #点的y值要在线段两个端点的y值中间,可以等于 if (y0 >= y1 and y0 <= y2): cross = crossProduct(pValue, sValue[0], sValue[1]); if (cross > 0): #点在线段的左边 return 'Left'; elif (cross < 0): #点在线段的右边 return 'Right'; return 'Nevermind'; #获取扫描线与线段的交点 #y方向的扫描线为平行于x轴且y值为某一定值的直线 def calcScanLineCrosspoint(seg, point): #传入SegLine类型和Point类型,这样方便比较 #SegLine是以y优先x其次由小大大排序的,终端点按排序规则大于起始端点 pValue = point.value(); sValue = seg.value(); x0, y0, x1, y1, x2, y2 = pValue[0], pValue[1], sValue[0][0], sValue[0][1],\ sValue[1][0], sValue[1][1]; #点的y值要在线段两个端点的y值中间,可以等于 if (y0 >= y1 and y0 <= y2): if y0 == y1: return sValue[0]; elif y0 == y2: return sValue[1]; else: x = x1 + (y0 - y1)/(y2 - y1)*(x2-x1); return [round(x, 2), y0]; return []; #</span>
$split = [[[2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [2.4, 5.4]], [[3.33, 5], [6, 3.86], [8, 3], [6, 9], [2.4, 5.4], [3.33, 5]]]
<span style="font-size:18px;">//
if (1) {
var r = 20;
config.setSector(1,1,1,1);
config.graphPaper2D(0, 0, r);
config.axis2D(0, 0, 250, 1.2);
//坐标轴设定
var scaleX = 2*r, scaleY = 2*r;
var spaceX = 2, spaceY = 2;
var xS = -10, xE = 10;
var yS = -10, yE = 10;
config.axisSpacing(xS, xE, spaceX, scaleX, 'X');
config.axisSpacing(yS, yE, spaceY, scaleY, 'Y');
var transform = new Transform();
//顶点
var a = [];
for (var i = 0; i < $vertex.length; i++) {
a.push($vertex[i][0]);
}
//显示变换
if (a.length > 0) {
a = transform.scale(transform.translate(a, 0, 0), scaleX/spaceX, scaleY/spaceY);
}
var lable = [];
for (var i = 0; i < 100; i++) {
lable.push(i.toFixed(0));
}
/*
//边集
var b = [];
for (var i = 0; i < $seg.length; i++) {
b.push([a[$seg[i][0]], a[$seg[i][1]]]);
}
var edges = b.length;
for (var i = 0; i < edges; i++) {
shape.multiLineDraw([].concat(b[i]), 'red');
}*/
var colorArray = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple'];
var seg = [];
var idx = xGlobal;
var len = $path2.length;
plot.setLineWidth(3);
seg = transform.scale(transform.translate($path2[idx%len], 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.multiLineDraw([].concat(seg), 'pink');
plot.fillText('路径: '+(idx%len).toFixed(0), 200, -150, 200);
for (var i = 0; i < $split.length; i++) {
seg = transform.scale(transform.translate($split[i], 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.multiLineDraw([].concat(seg), colorArray[i%7]);
}
//主要顶点
shape.pointDraw([].concat(a), 'blue', 1, 1, lable);
cPoint = transform.scale(transform.translate($center, 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.pointDraw([].concat([cPoint[idx%len]]), 'black');
/*
concavePoint = transform.scale(transform.translate($concave[idx%len], 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.pointDraw([].concat(concavePoint), 'orange');
*/
//次要顶点
var b = [];
for (var i = 0; i < 6; i++) {
b = [].concat($pointType[idx%len][i]);
//显示变换
if (b.length > 0) {
b = transform.scale(transform.translate(b, 0, 0), scaleX/spaceX, scaleY/spaceY);
shape.pointDraw([].concat(b), colorArray[(i-1)%7]);
}
}
}
//</span>
更多图片:
本节到此结束,欲知后事如何,请看下回分解。
相关文章推荐
- [从头学数学] 第273节 [计算几何] 多边形求交集
- [从头学数学] 第278节 [计算几何] 多边形周长和面积
- [从头学数学] 第277节 [计算几何] 任意多边形的内角
- [从头学数学] 第269节 [计算几何] 点在多边形内
- [从头学数学] 第284节 [计算几何] 生成随机多边形
- [从头学数学] 第285节 [计算几何] 区域划分
- [从头学数学] 第286节 [计算几何] 多边形的布尔运算(上)
- [从头学数学] 第287节 [计算几何] 多边形的布尔运算(中)
- [从头学数学] 第288节 [计算几何] 多边形的布尔运算(下)
- [从头学数学] 第275节 [计算几何] 多边形顶点的五种类型
- [从头学数学] 第267节 [计算几何] 路径规划
- [从头学数学] 第276节 [计算几何] 中心点与顶点的凹凸性
- [从头学数学] 第279节 [计算几何] 重心
- [从头学数学] 第264节 [计算几何] 点和线段
- [从头学数学] 第280节 [计算几何] 路径合并
- [从头学数学] 第281节 [计算几何] 路径分解
- [从头学数学] 第263节 [计算几何] 线段生成
- [从头学数学] 第268节 [计算几何] 环形路径
- [从头学数学] 第265节 [计算几何] 多线段求交点(扫描线法)
- [从头学数学] 第274节 [计算几何] 顶点树