这是我尝试在 Mathematica 中找到我的问题线框答案的一部分。
给定一组线段,如何连接两个连接并位于同一条线上的线段。例如考虑线段l1 = {(0,0), (1,1)}
和l2 = {(1,1), (2,2)}
。这两条线段可以合并为一条线段,即l3 = {(0,0), (2,2)}
。这是因为l1
和l2
共享点(1,1)
和每条线段的斜率是相同的。这是一个视觉效果:
l1 = JoinedCurve[{{{0, 2, 0}}}, {{{0, 0}, {1, 1}}}, CurveClosed -> {0}];
l2 = JoinedCurve[{{{0, 2, 0}}}, {{{1, 1}, {2, 2}}}, CurveClosed -> {0}];
Graphics[{Red, l1, Blue, l2}, Frame -> True]
需要注意的一点是,在上面的例子中l1
和l2
可以组合成由 3 个点指定的一条线,即{{0,0},{1,1},{2,2}}
.
这个问题的第一部分是:给定一组由 2 个点指定的线段,你如何减少这个集合以拥有一个重复点最少的集合。考虑这个组成的例子:
lines = {
{{0,0}, {1,1}},
{{3,3}, {2,2}},
{{2,2}, {1,1}},
{{1,1}, {0.5,0.5}},
{{0,1}, {0,2}},
{{2,3}, {0,1}}
}
我想要的是一个函数说它REDUCE
给我以下输出:
R = {
{{0,0}, {1,1}, {2,2}, {3,3}},
{{1,1}, {0.5,0.5}},
{{2,1}, {0,1}, {0,2}}
}
我们需要的唯一副本是{1,1}
. 我这样做的方法如下:我将第一行放入R
然后我查看了下一行,lines
并注意到没有端点与行中的端点匹配,R
因此我将此新行添加到R
. 中的下一行lines
是{{2,2},{1,1}}
,端点{1,1}
与中的第一行匹配,R
因此我将其附加{2,2}
到中R
。现在我添加{{1,1}, {0.5,0.5}}
,R
我也添加{{0,1}, {0,2}}
. 由于 in 的最后一行lines
有一个与 in 匹配的端点,R
所以我附加了它,所以我们有{{2,1}, {0,1}, {0,2}}
. 最后,我查看所有行,R
看看是否有任何端点匹配,在这种情况下,该行{{3,3}, {2,2}}
与第一行的右端点匹配R
所以我追加{3,3}
,从而消除了对{2,2}
.
这可能不是最好的方法,因为它可能不会给你最好的减少。无论如何,假设我们有这个归约函数,那么我们可以检查我们是否需要所有的点来描述一条线。这可以按如下方式完成:
如果我们有超过 3 个点来描述这条线,请检查前 3 个点是否共线,如果是,则删除中间的点并检查 2 个端点和一个新点的集合。如果它们不共线,则移动一个点并检查接下来的 3 个点。
我问这个问题的原因是因为我想减少描述二维图形所需的点数。尝试以下操作:
g1 = ListPlot3D[
{{0, -1, 0}, {0, 1, 0}, {-1, 0, 1}, {1, 0, 1}, {-1, 1, 1}},
Mesh -> {2, 2},
Boxed -> False,
Axes -> False,
ViewPoint -> {2, -2, 1},
ViewVertical -> {0, 0, 1}
]
以下Mathematica 8函数将 3D 对象更改为描述对象线框的线列表(线是 2 个点的列表):
G3TOG2INFO[g_] := Module[{obj, opt},
obj = ImportString[ExportString[g, "PDF", Background -> None], "PDF"][[1]];
opt = Options[obj];
obj = Cases[obj, _JoinedCurve, \[Infinity]];
obj = Map[#[[2]][[1]] &, obj];
{obj, opt}
]
请注意,在Mathematica 7中,我们必须替换_JoinedCurve
为_Line
. 应用g1
我们得到的函数
{lines, opt} = G3TOG2INFO[g1];
Row[{Graphics[Map[Line[#] &, lines], opt], Length@lines}]
那里有 90 条线段,但我们只需要 12 条(如果我在计算直线时没有犯任何错误)。
所以你有挑战。我们如何操作lines
以获得描述图形所需的最少信息量。