Wolfram mathematica Mathematica:非相交线段

Wolfram mathematica Mathematica:非相交线段,wolfram-mathematica,mathematica-8,Wolfram Mathematica,Mathematica 8,我们如何让Mathematica给我们一组不相交的线?在这种情况下,如果两条线有一个公共点(不是端点),则两条线相交。想想这个简单的例子: l1 = {{-1, 0}, {1, 0}}; l2 = {{0, -1}, {0, 1}}; lines = {l1, l2}; 其思想是创建一个函数,给定一组直线,该函数返回一组不相交的直线。如果存在这样的函数,比如说split,则 split[lines] 会是 { {{-1, 0}, {0,0}}, {{ 0, 0}, {1,0}}, {

我们如何让Mathematica给我们一组不相交的线?在这种情况下,如果两条线有一个公共点(不是端点),则两条线相交。想想这个简单的例子:

l1 = {{-1, 0}, {1, 0}};
l2 = {{0, -1}, {0, 1}};
lines = {l1, l2};
其思想是创建一个函数,给定一组直线,该函数返回一组不相交的直线。如果存在这样的函数,比如说
split
,则

split[lines]
会是

{
 {{-1, 0}, {0,0}},
 {{ 0, 0}, {1,0}}, 
 {{ 0,-1}, {0,0}}, 
 {{ 0, 0}, {0,1}}
}
函数检测到
{0,0}
是集合中两条直线的交点,为了有非相交直线,它在交点处打断线段,从而生成另外两条直线。如果原始输入包含更多行,则此过程会变得更复杂。在Mathematica中,有人知道如何在不使用循环的情况下有效地实现这一点吗?了解一种算法来判断是否正确可能会有所帮助

注意


这个问题是我试图找出答案的第二部分。请随意添加更多合适的标记。

如果您假设存在拆分,则需要将其应用于所有对;这些可能是由

ClearAll[permsnodups];
permsnodups[lp_] := DeleteDuplicates[Permutations[lp, {2}],
   ((#1[[1]] == #2[[1]]) &&(#1[[2]] == #2[[2]]) || 
   (#1[[1]] == #2[[2]]) && (#1[[2]] == #2[[1]])) &]
它是这样做的:
permsnodups[{a,b,c,d}]
提供
{a,b},{a,c},{b,c},{b,d},{b,d},{c,d}
,您可以在上面映射
拆分
函数(即这些都是对,确保如果
{a,b}
存在
{b,a}
并不是从那时起你就无缘无故地做了两次工作——这就像做$\sum{i,j>i}$而不是$\sum{i,j}$)

编辑:这里是一个
split
的实现(我被困在半个小时左右没有上网的状态,所以我手工计算出了相关的方程式,这不是基于你给出的链接,也不是优化的或漂亮的):

这就产生了

(可以四处移动定位器)。请注意,只要其中一行是垂直的,我的
split2
就会被零除(这可以修复,但我还没有完成)

无论如何,这一切都是非常缓慢和丑陋的。通过编译和制作列表(并使用您提供的链接)可以加快速度,但我目前的休息时间已经结束(或者是半个多小时前)。我稍后再谈这个问题


同时,一定要问是否有任何具体的问题(例如,如果你看不到垂直线有什么中断)。请注意,虽然这样做是为了满足您的要求,但如果您在一个行列表上进行映射,您将得到一个不完整的列表,您必须将其展平。但是,这就是您所要求的:)

如果您假设存在拆分,则需要将其应用于所有对;这些可能是由

ClearAll[permsnodups];
permsnodups[lp_] := DeleteDuplicates[Permutations[lp, {2}],
   ((#1[[1]] == #2[[1]]) &&(#1[[2]] == #2[[2]]) || 
   (#1[[1]] == #2[[2]]) && (#1[[2]] == #2[[1]])) &]
它是这样做的:
permsnodups[{a,b,c,d}]
提供
{a,b},{a,c},{b,c},{b,d},{b,d},{c,d}
,您可以在上面映射
拆分
函数(即这些都是对,确保如果
{a,b}
存在
{b,a}
并不是从那时起你就无缘无故地做了两次工作——这就像做$\sum{i,j>i}$而不是$\sum{i,j}$)

编辑:这里是一个
split
的实现(我被困在半个小时左右没有上网的状态,所以我手工计算出了相关的方程式,这不是基于你给出的链接,也不是优化的或漂亮的):

这就产生了

(可以四处移动定位器)。请注意,只要其中一行是垂直的,我的
split2
就会被零除(这可以修复,但我还没有完成)

无论如何,这一切都是非常缓慢和丑陋的。通过编译和制作列表(并使用您提供的链接)可以加快速度,但我目前的休息时间已经结束(或者是半个多小时前)。我稍后再谈这个问题


同时,一定要问是否有任何具体的问题(例如,如果你看不到垂直线有什么中断)。请注意,虽然这样做是为了满足您的要求,但如果您在一个行列表上进行映射,您将得到一个不完整的列表,您必须将其展平。但是,这正是您所要求的:)

为了确定交点,您还可以采用以下参数化方法,这不会遇到涉及笛卡尔方程的方法的常见问题(即除以零…):

f[t_,l_列表]:=l[[1]]+t(l[[2]]-l[[1]]
拆分[l1,l2]:=模块[{s},
如果[(s=圆环@

减少[f[t1,l1]==f[t2,l2]&&0为了确定交点,您还可以采用以下参数化方法,该方法不会遇到涉及笛卡尔方程的方法的常见问题(即除以零…):

f[t_,l_列表]:=l[[1]]+t(l[[2]]-l[[1]]
拆分[l1,l2]:=模块[{s},
如果[(s=圆环@

Reduce[f[t1,l1]==f[t2,l2]&&0我这里没有Mma,但是你想要的是使用标准线性代数来表示每一行,作为A.{x,y}=c,并使用LinearSolve找到两条直线的方程都为真的点。然后,检查解是否位于给定的两条直线段的端点之间。如果是这样,请在该点拆分直线。正如我对前面问题的回答一样,您希望对元组[Sort[lines],{2}]执行此操作。@Verbeia,什么是
元组[Sort[lines],{2}]
应该做什么?让我们假设
行的定义与我的帖子中的定义相同。只有当您有一个包含两行以上行的列表,并且希望检查所有可能的行对时,才需要Tuples函数。它所做的只是从包含两个以上元素的列表中创建一个包含所有可能的元素对的列表。ACL是下面的nswer处理重复的问题,可能是一个比元组更好的解决方案。我这里没有Mma,但您想要的是使用标准线性代数将每一行表示为a.{x,y}=c,并使用LinearSolve找到两条直线的方程均为真的点。然后,检查解是否位于给定的两条线段的端点之间。如果是,则在该点拆分直线。与我的
Manipulate[
Grid[{{Graphics[{Line[{p1, p2}, VertexColors \[Rule] {Red, Green}], 
  Line[{p3, p4}]},
        PlotRange \[Rule] 3, Axes \[Rule] True],
        (*Reap@split2[{{p1,p2},{p3,p4}}]//Last,*)
        If[
            Length@split2[{{p1, p2}, {p3, p4}}] \[Equal] 2,
            "not intersecting",
            "intersecting"]}}],
{{p1, {0, 1}}, Locator}, {{p2, {1, 1}}, Locator},
{{p3, {2.3, -.1}}, Locator}, {{p4, {2, 1}}, Locator}]
f[t_, l_List] := l[[1]] + t (l[[2]] - l[[1]])
split[l1_, l2_] := Module[{s},
  If[(s = ToRules@
       Reduce[f[t1, l1]==f[t2, l2] && 0 <t2< 1 && 0 <t1< 1, {t1,t2},Reals]) =={},
   Return[{l1, l2}],
   Return[{{f[0, l1], f[t1, l1] /. s}, {f[1, l1], f[t1, l1] /. s},
           {f[0, l2], f[t2, l2] /. s}, {f[1, l2], f[t2, l2] /. s}}]
   ]]