您的位置:首页 > 其它

[从头学数学] 第288节 [计算几何] 多边形的布尔运算(下)

2016-10-21 15:25 441 查看
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。

正剧开始:
星历2016年10月21日 14:37:23, 银河系厄尔斯星球中华帝国江南行省。

[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。





五、SVG绘图相关

<span style="font-size:18px;">#
#===============================================================================
# OffsetPolygons (+ ancilliary functions)
#===============================================================================

FloatPoint = namedtuple('FloatPoint', 'x y')
Rect = namedtuple('FloatPoint', 'left top right bottom')

def _GetUnitNormal(pt1, pt2):
if pt2.x == pt1.x and pt2.y == pt1.y:
return FloatPoint(0.0, 0.0)
dx = pt2.x - pt1.x
dy = pt2.y - pt1.y
f = 1.0 / math.hypot(dx, dy)
dx = float(dx) * f
dy = float(dy) * f
return FloatPoint(dy, -dx)

def _BuildArc(pt, a1, a2, r, limit):
arcFrac = abs(a2 - a1) / (2 * math.pi);
steps = int(arcFrac * math.pi / math.acos(1 - limit / abs(r)))
if steps < 2: steps = 2
elif steps > 222.0 * arcFrac:
steps = int(222.0 * arcFrac)

result = []
y = math.sin(a1)
x = math.cos(a1)
s = math.sin((a2-a1)/steps)
c = math.cos((a2-a1)/steps)
for _ in range(steps+1):
result.append(FloatPoint(pt.x + round(x * r), pt.y + round(y * r)))
x2 = x
x = x * c - s * y # cross product & dot product here ...
y = x2 * s + y * c # avoids repeat calls to the much slower sin() & cos()

return result

def _GetBounds(pts):
left = None
for poly in pts:
for pt in poly:
left = pt.x
top = pt.y
right = pt.x
bottom = pt.y
break
break

for poly in pts:
for pt in poly:
if pt.x < left: left = pt.x
if pt.x > right: right = pt.x
if pt.y < top: top = pt.y
if pt.y > bottom: bottom = pt.y
if left is None: return Rect(0, 0, 0, 0)
else: return Rect(left, top, right, bottom)

def _GetLowestPt(poly):
# precondition: poly must not be empty
result = poly[0]
for pt in poly:
if pt.y > result.y or (pt.y == result.y and pt.x < result.x):
result = pt
return result

def _StripDupPts(poly):
if poly == []: return poly
for i in range(1, len(poly)):
if _PointsEqual(poly[i-1], poly[i]): poly.pop(i)
i = len(poly) -1
while i > 0 and _PointsEqual(poly[i], poly[0]):
poly.pop(i)
i -= 1
return poly

def _OffsetInternal(polys, isPolygon, delta, jointype = JoinType.Square, endtype = EndType.Square, limit = 0.0):

def _DoSquare(pt):
pt1 = Point(round(pt.x + Normals[k].x * delta), round(pt.y + Normals[k].y * delta))
pt2 = Point(round(pt.x + Normals[j].x * delta), round(pt.y + Normals[j].y * delta))
if (Normals[k].x*Normals[j].y-Normals[j].x*Normals[k].y) * delta >= 0:
a1 = math.atan2(Normals[k].y, Normals[k].x)
a2 = math.atan2(-Normals[j].y, -Normals[j].x)
a1 = abs(a2 - a1);
if a1 > math.pi: a1 = math.pi * 2 - a1
dx = math.tan((math.pi - a1)/4) * abs(delta)

pt1 = Point(round(pt1.x -Normals[k].y * dx), round(pt1.y + Normals[k].x * dx))
result.append(pt1)
pt2 = Point(round(pt2.x + Normals[j].y * dx), round(pt2.y - Normals[j].x * dx))
result.append(pt2)
else:
result.append(pt1)
result.append(pt)
result.append(pt2)

def _DoMiter(pt, r):
if ((Normals[k].x* Normals[j].y - Normals[j].x * Normals[k].y) * delta >= 0):
q = delta / r;
result.append(Point(round(pt.x + (Normals[k].x + Normals[j].x) *q),
round(pt.y + (Normals[k].y + Normals[j].y) *q)))
else:
pt1 = Point(round(pt.x + Normals[k].x * delta), \
round(pt.y + Normals[k].y * delta))
pt2 = Point(round(pt.x + Normals[j].x * delta), \
round(pt.y + Normals[j].y * delta))
result.append(pt1)
result.append(pt)
result.append(pt2)

def _DoRound(pt, limit):
pt1 = Point(round(pt.x + Normals[k].x * delta), \
round(pt.y + Normals[k].y * delta))
pt2 = Point(round(pt.x + Normals[j].x * delta), \
round(pt.y + Normals[j].y * delta))
result.append(pt1)
if (Normals[k].x * Normals[j].y - Normals[j].x * Normals[k].y) *delta >= 0:
if (Normals[j].x * Normals[k].x + Normals[j].y * Normals[k].y) < 0.985:
a1 = math.atan2(Normals[k].y, Normals[k].x)
a2 = math.atan2(Normals[j].y, Normals[j].x)
if (delta > 0) and (a2 < a1): a2 = a2 + math.pi * 2
elif (delta < 0) and (a2 > a1): a2 = a2 - math.pi * 2
arc = _BuildArc(pt, a1, a2, delta, limit)
result.extend(arc)
else:
result.append(pt)
result.append(pt2)

def _OffsetPoint(jointype, limit):
if jointype == JoinType.Miter:
r = 1.0 + (Normals[j].x * Normals[k].x + Normals[j].y * Normals[k].y)
if (r >= rmin): _DoMiter(pts[j], r)
else: _DoSquare(pts[j])
elif jointype == JoinType.Square: _DoSquare(pts[j])
else: _DoRound(pts[j], limit)
return j

if delta == 0: return polys
rmin = 0.5
if (jointype == JoinType.Miter):
if (limit > 2):
rmin = 2.0 / (limit * limit)
limit = 0.25; #just in case endtype == EndType.Round
else:
if (limit <= 0): limit = 0.25
elif (limit > abs(delta)): limit = abs(delta)

res = []
ppts = polys[:]
for pts in ppts:
Normals = []
result = []
cnt = len(pts)

if (cnt == 0 or cnt < 3 and delta <= 0): continue
elif (cnt == 1):
res.append(_BuildArc(pts[0], 0, 2 * math.pi, delta, limit))
continue

forceClose = _PointsEqual(pts[0], pts[cnt - 1])
if (forceClose): cnt -=1

for j in range(cnt -1):
Normals.append(_GetUnitNormal(pts[j], pts[j+1]))
if isPolygon or forceClose:
Normals.append(_GetUnitNormal(pts[cnt-1], pts[0]))
else:
Normals.append(Normals[cnt-2])

if (isPolygon or forceClose):
k = cnt - 1
for j in range(cnt):
k = _OffsetPoint(jointype, limit)
res.append(result)

if not isPolygon:
result = []
delta = -delta
k = cnt - 1
for j in range(cnt):
k = _OffsetPoint(jointype, limit)
delta = -delta
res.append(result[::-1])

else:
# offset the polyline going forward ...
k = 0;
for j in range(1, cnt-1):
k = _OffsetPoint(jointype, limit)

# handle the end (butt, round or square) ...
if (endtype == EndType.Butt):
j = cnt - 1
pt1 = Point(round(float(pts[j].x) + Normals[j].x * delta), \
round(float(pts[j].y) + Normals[j].y * delta))
result.append(pt1)
pt1 = Point(round(float(pts[j].x) - Normals[j].x * delta), \
round(float(pts[j].y) - Normals[j].y * delta))
result.append(pt1)
else:
j = cnt - 1;
k = cnt - 2;
Normals[j] = DoublePoint(-Normals[j].x, -Normals[j].y)
if (endtype == EndType.Square): _DoSquare(pts[j])
else: _DoRound(pts[j], limit)

# re-build Normals ...
for j in range(cnt -1, 0, -1):
Normals[j] = DoublePoint(-Normals[j -1].x, -Normals[j -1].y)
Normals[0] = DoublePoint(-Normals[1].x, -Normals[1].y)

# offset the polyline going backward ...
k = cnt -1;
for j in range(cnt -2, 0, -1):
k = _OffsetPoint(jointype, limit)

# finally handle the start (butt, round or square) ...
if (endtype == EndType.Butt):
pt1 = Point(round(float(pts[0].x) - Normals[0].x * delta), \
round(float(pts[0].y) - Normals[0].y * delta))
result.append(pt1)
pt1 = Point(round(float(pts[0].x) + Normals[0].x * delta), \
round(float(pts[0].y) + Normals[0].y * delta))
result.append(pt1)
else:
j = 0
k = 1
if (endtype == EndType.Square): _DoSquare(pts[0])
else: _DoRound(pts[0], limit)
res.append(result)

c = Clipper()
c.AddPolygons(res, PolyType.Subject)
if delta > 0:
c.Execute(ClipType.Union, res, PolyFillType.Positive, PolyFillType.Positive)
else:
bounds = _GetBounds(res)
outer = []
outer.append(Point(bounds.left-10, bounds.bottom+10))
outer.append(Point(bounds.right+10, bounds.bottom+10))
outer.append(Point(bounds.right+10, bounds.top-10))
outer.append(Point(bounds.left-10, bounds.top-10))
c.AddPolygon(outer, PolyType.Subject)
c.Execute(ClipType.Union, res, PolyFillType.Negative, PolyFillType.Negative)
if len(res) > 0: res.pop(0)
for poly in res:
poly = poly[::-1]
return res

def OffsetPolygons(polys, delta, jointype = JoinType.Square, limit = 0.0, autoFix = True):
if not autoFix:
return _OffsetInternal(polys, True, delta, jointype, EndType.Butt, limit)
pts = polys[:]
botPoly = None
botPt = None
for poly in pts:
poly = _StripDupPts(poly)
if len(poly) < 3: continue
bot = _GetLowestPt(poly)
if botPt is None or (bot.y > botPt.y) or \
(bot.y == botPt.y and bot.x < botPt.x):
botPt = bot
botPoly = poly
if botPt is None: return []
# if the outermost polygon has the wrong orientation,
# reverse the orientation of all the polygons ...
if Area(botPoly) < 0.0:
for i in range(len(pts)):
pts[i] = pts[i][::-1]
return _OffsetInternal(pts, True, delta, jointype, EndType.Butt, limit)

def OffsetPolyLines(polys, delta, jointype = JoinType.Square, endtype = EndType.Square, limit = 0.0):
polys2 = polys[:]
for p in polys2:
if p == []: continue
for i in range(1, len(p)):
if _PointsEqual(p[i-1], p[i]): p.pop(i)

if endtype == EndType.Closed:
for i in range(len(polys2)):
polys2.append(polys2[i][::-1])
return _OffsetInternal(polys2, True, delta, jointype, EndType.Butt, limit)
else:
return _OffsetInternal(polys2, False, delta, jointype, endtype, limit)

def _DistanceSqrd(pt1, pt2):
dx = (pt1.x - pt2.x)
dy = (pt1.y - pt2.y)
return (dx*dx + dy*dy)

def _ClosestPointOnLine(pt, linePt1, linePt2):
dx = linePt2.x - linePt1.x
dy = linePt2.y - linePt1.y
if (dx == 0 and dy == 0):
return DoublePoint(linePt1.x, linePt1.y)
q = ((pt.x-linePt1.x)*dx + (pt.Y-linePt1.Y)*dy) / (dx*dx + dy*dy)
return DoublePoint(
(1-q)*linePt1.X + q*linePt2.X,
(1-q)*linePt1.Y + q*linePt2.Y)

def _SlopesNearColinear(pt1, pt2, pt3, distSqrd):
if _DistanceSqrd(pt1, pt2) > _DistanceSqrd(pt1, pt3): return False
cpol = _ClosestPointOnLine(pt2, pt1, pt3);
dx = pt2.x - cpol.x
dy = pt2.y - cpol.y
return (dx*dx + dy*dy) < distSqrd

def _PointsAreClose(pt1, pt2, distSqrd):
dx = pt1.x - pt2.x
dy = pt1.y - pt2.y
return (dx * dx) + (dy * dy) <= distSqrd

def CleanPolygon(poly, distance = 1.415):
distSqrd = distance * distance
highI = len(poly) -1
while (highI > 0 and _PointsEqual(poly[highI], poly[0])): highI -= 1
if (highI < 2): return []
pt = poly[highI]
result = []
i = 0
while True:
while (i < highI and _PointsAreClose(pt, poly[i+1], distSqrd)): i +=2
i2 = i
while (i < highI and (_PointsAreClose(poly[i], poly[i+1], distSqrd) or \
_SlopesNearColinear(pt, poly[i], poly[i+1], distSqrd))): i +=1
if i >= highI: break
elif i != i2: continue
pt = poly[i]
i +=1
result.append(pt)

if (i <= highI): result.append(poly[i])
j = len(result)
if (j > 2 and _SlopesNearColinear(result[j-2], result[j-1], result[0], distSqrd)):
del result[j-1:]
if len(result) < 3: return []
else: return result

def CleanPolygons(polys, distance = 1.415):
result = []
for poly in polys:
result.append(CleanPolygon(poly, distance = 1.415))
return result

def SimplifyPolygon(poly, fillType):
result = []
c = Clipper();
c.ForceSimple = True
c.AddPolygon(poly, PolyType.Subject);
c.Execute(ClipType.Union, result, fillType, fillType)
return result

def SimplifyPolygons(polys, fillType):
result = []
c = Clipper();
c.ForceSimple = True
c.AddPolygons(polys, PolyType.Subject);
c.Execute(ClipType.Union, result, fillType, fillType)
return result

#===============================================================================
# SVGBuilder
#===============================================================================
class SVGBuilder(object):

def HtmlColor(self, val):
return "#{0:06x}".format(val & 0xFFFFFF)

def AlphaClr(self, val):
return "{0:.2f}".format(float(val >> 24)/255)

class StyleInfo(object):
def __init__(self):
self.fillType = PolyFillType.EvenOdd
self.brushClr = 0
self.penClr = 0
self.penWidth = 0.8
self.showCoords = False

class StyleInfoPlus(StyleInfo):

def __init__(self):
SVGBuilder.StyleInfo.__init__(self)
self.polygons = []
self.textlines = []

def __init__(self):
self.GlobalStyle = SVGBuilder.StyleInfo()
self.PolyInfoList = []
self.PathHeader = " <path d=\""
self.PathFooter = "\"\n style=\"fill:{0}; fill-opacity:{1}; fill-rule:{2}; stroke:{3}; stroke-opacity:{4}; stroke-width:{5:.2f};\" filter=\"url(#Gamma)\"/>\n\n"
self.Header = """<?xml version=\"1.0\" standalone=\"no\"?>
<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"
\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">
\n<svg width=\"{0}px\" height=\"{1}px\" viewBox=\"0 0 {0} {1}\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">
<defs>
<filter id="Gamma">
<feComponentTransfer>
<feFuncR type="gamma" amplitude="1" exponent="0.3" offset="0" />
<feFuncG type="gamma" amplitude="1" exponent="0.3" offset="0" />
<feFuncB type="gamma" amplitude="1" exponent="0.3" offset="0" />
</feComponentTransfer>
</filter>
</defs>\n\n"""

def AddPolygon(self, poly, brushColor, penColor):
if poly is None or len(poly) == 0: return
pi = self.StyleInfoPlus()
pi.penWidth = self.GlobalStyle.penWidth
pi.fillType = self.GlobalStyle.fillType
pi.showCoords = self.GlobalStyle.showCoords
pi.brushClr = brushColor
pi.penClr = penColor
pi.polygons.append(poly)
self.PolyInfoList.append(pi)

def AddPolygons(self, polys, brushColor, penColor):
if polys is None or len(polys) == 0: return
pi = self.StyleInfoPlus()
pi.penWidth = self.GlobalStyle.penWidth
pi.fillType = self.GlobalStyle.fillType
pi.showCoords = self.GlobalStyle.showCoords
pi.brushClr = brushColor
pi.penClr = penColor
pi.polygons = polys
self.PolyInfoList.append(pi)

def SaveToFile(self, filename, invScale = 1.0, margin = 10):
if len(self.PolyInfoList) == 0: return False
if invScale == 0: invScale = 1.0
if margin < 0: margin = 0
pi = self.PolyInfoList[0]
# get bounding rect ...
left = right = pi.polygons[0][0].x
top = bottom = pi.polygons[0][0].y
for pi in self.PolyInfoList:
for p in pi.polygons:
for ip in p:
if ip.x < left: left = ip.x
if ip.x > right: right = ip.x
if ip.y < top: top = ip.y
if ip.y > bottom: bottom = ip.y
left *= invScale
top *= invScale
right *= invScale
bottom *= invScale
offsetX = -left + margin
offsetY = -top + margin

f = open(filename, 'w')
m2 = margin * 2
f.write(self.Header.format(right - left + m2, bottom - top + m2))
for pi in self.PolyInfoList:
f.write(self.PathHeader)
for p in pi.polygons:
cnt = len(p)
if cnt < 3: continue
f.write(" M {0:.2f} {1:.2f}".format(p[0].x * invScale + offsetX, p[0].y * invScale + offsetY))
for i in range(1,cnt):
f.write(" L {0:.2f} {1:.2f}".format(p[i].x * invScale + offsetX, p[i].y * invScale + offsetY))
f.write(" z")
fillRule = "evenodd"
if pi.fillType != PolyFillType.EvenOdd: fillRule = "nonzero"
f.write(self.PathFooter.format(self.HtmlColor(pi.brushClr),
self.AlphaClr(pi.brushClr), fillRule,
self.HtmlColor(pi.penClr), self.AlphaClr(pi.penClr), pi.penWidth))

if (pi.showCoords):
f.write("<g font-family=\"Verdana\" font-size=\"11\" fill=\"black\">\n\n")
for p in pi.polygons:
cnt = len(p)
if cnt < 3: continue
for pt in p:
x = pt.x * invScale + offsetX
y = pt.y * invScale + offsetY
f.write("<text x=\"{0}\" y=\"{1}\">{2},{3}</text>\n".format(x, y, pt.x, pt.y))
f.write("\n")
f.write("</g>\n")

f.write("</svg>\n")
f.close()
return True

#</span>





<span style="font-size:18px;">#
def tmp_6():
#===============================================================================
# Main entry ...
#===============================================================================

'''
scaleExp = 0
scale = math.pow(10, scaleExp)
invScale = 1.0 / scale

subj, clip = [], []
#load saved subject and clip polygons ...
#subj = LoadFile('./subj.txt')
#clip = LoadFile('./clip.txt')

# Generate random subject and clip polygons ...
subj.append(RandomPoly(640 * scale, 480 * scale, 100))
clip.append(RandomPoly(640 * scale, 480 * scale, 100))
#SaveToFile('./subj2.txt', subj, scale)
#SaveToFile('./clip2.txt', clip, scale)

# Load the polygons into Clipper and execute the boolean clip op ...
c = Clipper()
solution = []
pft = PolyFillType.EvenOdd

c.AddPolygons(subj, PolyType.Subject)
c.AddPolygons(clip, PolyType.Clip)
result = c.Execute(ClipType.Intersection, solution, pft, pft)

SaveToFile('./solution2.txt', solution, scale)
'''

scaleExp = 0
scale = math.pow(10, scaleExp)
invScale = 1.0 / scale

# Load the polygons into Clipper and execute the boolean clip op ...
c = Clipper()
solution = []
pft = PolyFillType.EvenOdd

vert_subj = [[199, 133], [577, 464], [468, 386], [130, 128], [336, 140], [324, 418], [91, 223], [67, 455], [168, 458], [639, 227]]
vert_clip = [[233, 423], [193, 76], [369, 373], [538, 416], [155, 301], [215, 323], [82, 473], [136, 405], [466, 145], [250, 336], [480, 218], [135, 320], [492, 135], [40, 361], [467, 323], [347, 26]]

trans = Transform();
vert_subj = trans.xyzSort(vert_subj);
vert_clip = trans.xyzSort(vert_clip);

'''
print(vert_subj);
print(vert_clip);
'''

subj, clip = [], [];
for i in range(len(vert_subj)):
subj.append(Point(vert_subj[i][0], vert_subj[i][1]));

for i in range(len(vert_clip)):
clip.append(Point(vert_clip[i][0], vert_clip[i][1]));

c.AddPolygons([subj], PolyType.Subject)
c.AddPolygons([clip], PolyType.Clip)
result = c.Execute(ClipType.Intersection, solution, pft, pft)

# Create an SVG file to display what's happened ...
svgBuilder = SVGBuilder()
#svgBuilder.GlobalStyle.showCoords = True
svgBuilder.GlobalStyle.fillType = pft
svgBuilder.AddPolygons([subj], 0x402020FF, 0x802020FF)
#svgBuilder.GlobalStyle.showCoords = False
svgBuilder.AddPolygons([clip], 0x40FFFF20, 0x80FF2020)
svgBuilder.GlobalStyle.penWidth = 0.6
svgBuilder.AddPolygons(solution, 0x60138013, 0xFF003300)

holes = []
for poly in solution:
if Area(poly) < 0: holes.append(poly)
svgBuilder.AddPolygons(holes, 0x0, 0xFFFF0000)
svgBuilder.SaveToFile('./test.svg', invScale, 100)
print('保存文件完毕');

'''
if result: os.startfile('test.svg') # call(('open', 'test.svg')) # print("finished") #
else: print("failed")
'''
#</span>
<span style="font-size:18px;">//
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

<svg width="799.0px" height="647.0px" viewBox="0 0 799.0 647.0" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="Gamma">
<feComponentTransfer>
<feFuncR type="gamma" amplitude="1" exponent="0.3" offset="0" />
<feFuncG type="gamma" amplitude="1" exponent="0.3" offset="0" />
<feFuncB type="gamma" amplitude="1" exponent="0.3" offset="0" />
</feComponentTransfer>
</filter>
</defs>

<path d=" M 127.00 529.00 L 151.00 297.00 L 190.00 202.00 L 228.00 532.00 L 259.00 207.00 L 384.00 492.00 L 396.00 214.00 L 528.00 460.00 L 637.00 538.00 L 699.00 301.00 z"
style="fill:#2020ff; fill-opacity:0.25; fill-rule:evenodd; stroke:#2020ff; stroke-opacity:0.50; stroke-width:0.80;" filter="url(#Gamma)"/>

<path d=" M 100.00 435.00 L 142.00 547.00 L 195.00 394.00 L 196.00 479.00 L 215.00 375.00 L 253.00 150.00 L 275.00 397.00 L 293.00 497.00 L 310.00 410.00 L 407.00 100.00 L 429.00 447.00 L 526.00 219.00 L 527.00 397.00 L 540.00 292.00 L 552.00 209.00 L 598.00 490.00 z"
style="fill:#ffff20; fill-opacity:0.25; fill-rule:evenodd; stroke:#ff2020; stroke-opacity:0.50; stroke-width:0.80;" filter="url(#Gamma)"/>

<path d=" M 136.00 439.00 L 178.00 444.00 L 152.00 519.00 L 134.00 526.00 L 129.00 512.00 z M 575.00 350.00 L 598.00 490.00 L 565.00 486.00 L 528.00 460.00 L 488.00 385.00 L 527.00 370.00 L 527.00 397.00 L 531.00 368.00 z M 195.00 394.00 L 196.00 446.00 L 202.00 446.00 L 196.00 479.00 L 196.00 446.00 L 178.00 444.00 z M 396.00 214.00 L 417.00 253.00 L 427.00 410.00 L 387.00 425.00 L 385.00 466.00 L 372.00 465.00 L 360.00 436.00 L 387.00 425.00 z M 259.00 212.00 L 275.00 397.00 L 286.00 455.00 L 301.00 457.00 L 300.00 460.00 L 287.00 465.00 L 286.00 455.00 L 236.00 450.00 z M 326.00 359.00 L 360.00 436.00 L 306.00 458.00 L 301.00 457.00 L 310.00 410.00 z M 212.00 392.00 L 218.00 448.00 L 202.00 446.00 z M 470.00 351.00 L 488.00 385.00 L 449.00 401.00 z"
style="fill:#138013; fill-opacity:0.38; fill-rule:evenodd; stroke:#003300; stroke-opacity:1.00; stroke-width:0.60;" filter="url(#Gamma)"/>

</svg>
//</span>




<span style="font-size:18px;">//
if (1) {
var r = 20;
config.setSector(8,15,7,2);
config.graphPaper2D(0, 0, r);
config.axis2D(0, 0, 450, 1.2);

//坐标轴设定
var scaleX = 2*r, scaleY = 2*r;
var spaceX = 50, spaceY = 50;
var xS = 0, xE = 640;
var yS = 0, yE = 480;
config.axisSpacing(xS, xE, spaceX, scaleX, 'X');
config.axisSpacing(yS, yE, spaceY, scaleY, 'Y');

var transform = new Transform();

var lable = [];
for (var i = 0; i < 100; i++) {
lable.push(i.toFixed(0));
}

var colorArray = ['#FF8888', 'orange', 'yellow', 'green', 'cyan', '#8888FF', 'purple'];
var color = 0;

var seg = [];

var solus = $solution.length;

for (var i = 0; i < solus; i++) {
seg = transform.scale($solution[i], scaleX/spaceX, scaleY/spaceY);
shape.fillDraw([].concat(seg), colorArray[i%7]);
}

//主多边形
var seg_subj = transform.scale($vert_subj, scaleX/spaceX, scaleY/spaceY);
//从多边形
var seg_clip = transform.scale($vert_clip, scaleX/spaceX, scaleY/spaceY);

//shape.fillDraw([].concat(seg_subj), colorArray[0]);

plot.setGlobalAlpha(0.2);
shape.fillDraw([].concat(seg_subj), 'red');
shape.fillDraw([].concat(seg_clip), 'blue');
plot.setGlobalAlpha(1.0);
shape.pointDraw([].concat(seg_subj), 'red', 1, 1, lable);
shape.pointDraw([].concat(seg_clip), 'blue', 1, 1, lable);

plot.fillText('图:主多边形和从多边形的交集', 10, 60, 300);

}
//</span>

$vert_subj = [[67, 455], [91, 223], [130, 128], [168, 458], [199, 133], [324, 418], [336, 140], [468, 386], [577, 464], [639, 227]]

$vert_clip = [[40, 361], [82, 473], [135, 320], [136, 405], [155, 301], [193, 76], [215, 323], [233, 423], [250, 336], [347, 26], [369, 373], [466, 145], [467, 323], [480, 218], [492, 135], [538, 416]]

$solution = [[[76, 365], [118, 370], [92, 445], [74, 452], [69, 438]], [[515, 276], [538, 416], [505, 412], [468, 386], [428, 311], [467, 296], [467, 323], [471, 294]], [[135, 320], [136, 372], [142, 372], [136, 405], [136, 372], [118, 370]], [[336, 140], [357,
179], [367, 336], [327, 351], [325, 392], [312, 391], [300, 362], [327, 351]], [[199, 138], [215, 323], [226, 381], [241, 383], [240, 386], [227, 391], [226, 381], [176, 376]], [[266, 285], [300, 362], [246, 384], [241, 383], [250, 336]], [[152, 318], [158,
374], [142, 372]], [[410, 277], [428, 311], [389, 327]]]

本节到此结束,欲知后事如何,请看下回分解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: