检测线是否在 Google 图表或 Plot.ly 中相交

Detect if Lines Intersect in Google Charts or Plot.ly

我见过声称可以输入坐标的脚本,如果它们相交,它会告诉你,但我有几个 "lines" 的 X、Y 值数组,但我如何循环遍历点以确定它们是否相交?

我附上了我的图表照片,如你所见,最终我的图表交叉了,我只想知道我的值是否交叉(相交)。

我如何运行通过这个找出是否有任何交集?

var Test = {
 x: [8043, 10695, 13292, 17163, 20716, 25270],
 y: [1000,   274,   100,  27.4,    10,  2.74],
 fill: 'tozeroy',
 type: 'scatter',
 name: 'Test'
};


var Test2 = {
 x: [8043, 10063, 12491, 16081, 19408, 23763],
 y: [1000,   274,   100,  27.4,    10,  2.74],
 fill: 'tozeroy',
 type: 'scatter',
 name: 'Test2'
};

var Test3 = {
 x: [4700,  5943,  7143,  8841, 10366, 13452],
 y: [1000,   274,   100,  27.4,    10,  2.74],
 fill: 'tozeroy',
 type: 'scatter',
 name: 'Test3'
};


var data = [Test, Test2, Test3];

var layout = {
width: 700,
height: 700,
xaxis: {
 type: 'log',
 range: [3,5] 
},
yaxis: {
 type: 'log',
 range: [-2,3] 
}

};

Plotly.newPlot('myDiv', data,layout);

路径拦截

此回答是 您最不满的问题的后续回答。

下面的代码片段将找到 tables 中路径的截距,如该问题示例数据中的结构,使用来自上述答案的可能评论中的答案 link 的修改后的截距函数.

注意 我假设示例数据中的每个 table 例如 Test 代表一条曲线(路径作为一组线段)并且拦截预计不会在 table 内,而是在 table 之间。

基本解决方案

它通过检查一个 table 中的每个线段与另一个 table 中的每个线段并将所有截距存储在一个数组中来实现这一点。

注意如果在直线的起点或终点发现截距,它可能会出现在截距数组中两次,因为截距测试包括这些点。

注意 平行的线,即使它们有匹配的起点和/或终点也不会算作截距。

该示例是 运行 针对示例数据的,并且有一个详细的控制台输出来指导,如果需要,您可以处理您正在争论的任何数据集。可以删除控制台日志而不会产生不良影响。

var Test = {
 x: [8043, 10695, 13292, 17163, 20716, 25270],
 y: [1000,   274,   100,  27.4,    10,  2.74],
 fill: 'tozeroy',
 type: 'scatter',
 name: 'Test'
};


var Test2 = {
 x: [8043, 10063, 12491, 16081, 19408, 23763],
 y: [1000,   274,   100,  27.4,    10,  2.74],
 fill: 'tozeroy',
 type: 'scatter',
 name: 'Test2'
};

var Test3 = {
 x: [4700,  5943,  7143,  8841, 10366, 13452],
 y: [1000,   274,   100,  27.4,    10,  2.74],
 fill: 'tozeroy',
 type: 'scatter',
 name: 'Test3'
};


// Copy from here to end comment and place into you page (code base)

// lines outputting to the console eg console.log are just there to help you out
// and can be removed
const lineIntercepts = (() => {
 const Point = (x, y) => ({x, y});
 const Line = (p1, p2) => ({p1, p2});
 const Vector = line => Point(line.p2.x - line.p1.x, line.p2.y - line.p1.y);
 function interceptSegs(line1, line2) {
  const a = Vector(line1), b = Vector(line2);
  const c = a.x * b.y - a.y * b.x;
  if (c) {
   const e = Point(line1.p1.x - line2.p1.x, line1.p1.y - line2.p1.y);
   const u = (a.x * e.y - a.y * e.x) / c;
   if (u >= 0 && u <= 1) {
    const u = (b.x * e.y - b.y * e.x) / c;
    if (u >= 0 && u <= 1) {
     return Point(line1.p1.x + a.x * u, line1.p1.y + a.y * u);
    }
   }
  }
 } 
 const PointFromTable = (t, idx) => Point(t.x[idx], t.y[idx]);
 const LineFromTable = (t, idx) => Line(PointFromTable(t, idx++), PointFromTable(t, idx));
 return function (table1, table2) {
  const results = [];
  var i = 0, j;
  while (i < table1.x.length - 1) {
   
   const line1 = LineFromTable(table1, i);
   j = 0;
   while (j < table2.x.length - 1) {
    const line2 = LineFromTable(table2, j);
    const point = interceptSegs(line1, line2);
    if (point) { 
     results.push({
      description: `'${table1.name}' line seg index ${i}-${i+1} intercepts '${table2.name}' line seg index ${j} - ${j+1}`,

                    // The description (line above) can be replaced 
                    // with relevant data as follows
/*  remove this line to include additional info per intercept
                        tableName1: table1.name,
                        tableName2: table2.name,
                        table_1_PointStartIdx: i,
                        table_1_PointEndIdx: i + 1,   
                        table_2_PointStartIdx: j,
                        table_2_PointEndIdx: j + 1,   
and remove this line */

      x: point.x,
      y: point.y,
     });
    }
    j ++;
   }
   i++;
  }
  if (results.length) {
   console.log("Found " + results.length + " intercepts for '" + table1.name + "' and '" + table2.name + "'");
   console.log(results);
   return results;
  } 
  console.log("No intercepts found for  '" + table1.name + "' and '" + table2.name + "'");
 }
})();

// end of code



// Test and example code only from here down.     
var res1 = lineIntercepts(Test, Test2);    
var res2 = lineIntercepts(Test, Test3);    
var res3 = lineIntercepts(Test2, Test3);    
          
          

  

使用上面的函数

这段代码说明了如何从函数结果中提取截距

// find all the intercepts for the paths in tabels Test and Test2
const results = lineIntercepts(Test, Test2); // pass two tables

// If results not undefined then intercepts have been found
if (results) { // results is an array of found intercepts

    // to get the point/s as there could be several
    for (const intercept of results) {  // loop over every intercept 

        // a single intercept coordinate
        const x = intercept.x;  // get x
        const y = intercept.y;  // get y
    }
}

更好的解决方案

这些路径看起来非常像是某个函数的绘图,因此还有更简单的解决方案。

我不会列出代码行,而是会指导您使用图形计算器,以防您不知道这些有用的节省时间的方法。他们会在输入数据所需的时间内解决您的问题(通过复制和粘贴不会很长)

在线图形计算器示例应用程序 Geogebra and Desmos 等等。