检测线条是否在Google图表或Plot.ly中相交 [英] Detect if Lines Intersect in Google Charts or Plot.ly

查看:95
本文介绍了检测线条是否在Google图表或Plot.ly中相交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过一些脚本,这些脚本声称可以输入坐标,并且会告诉您它们是否相交,但是我有几个线"的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);

解决方案

路径拦截

此答案是我的答案针对您最迫切的问题的提示.

下面的代码段将使用答案链接中的修改后的拦截函数在上述问题的注释中找到表中路径的截距(如本问题示例数据所示).

注意,我假设示例数据中的每个表(例如Test)都代表一条曲线(路径为一组线段),并且在表内而不是在表之间应该有截距

基本解决方案

通过将一个表中的每个线段与另一个表中的每个线段进行检查,并将所有截距存储在数组中,来实现此目的.

请注意,如果在某行的起点或终点发现了截距,则该截距可能会在截距数组中出现两次,因为截距测试包括这些点.

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

该示例针对示例数据运行,并具有详细的控制台输出,以在需要时指导您处理要处理的数据集.控制台日志可以删除而不会产生不良影响.

 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

I've included a photo of my graph and as you see, eventually my plots cross over, I just want to know if my values ever cross over (intersect).

How do I run through this to find out if any intersection ever occurs?

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);

解决方案

Path intercepts

This answer is a follow on from my answer to your most resent question.

The code snippet below will find the intercepts of the paths in the tables as structured in this questions example data using a modified intercept function from the answer link in may comment from aforementioned answer.

Note I am assuming that each table eg Test in your example data represents a curve (Path as a set of line segments) and that intercepts are not expected within a table but rather between tables.

Basic solution

It does this by checking each line segment in one table against each line segment in the other and storing all intercepts in an array.

Note that if a intercept is found at the start or end point of a line it may appear in the array of intercepts twice as the intercept test includes these points.

Note lines that are parallel, even if they have matching start and or end points will not count as intercepts.

The example is run against the example data and has a verbose console output to guide, if needed, you working through what ever data sets you are wrangling. The console logs can be removed without ill effect.

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);    
          
          

		

Using the above function

This bit of code illustrates how you extract intercepts from the function results

// 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
    }
}

Better solutions

The paths look very much like they are a plot of some function thus there are even simpler solutions.

Rather than list out lines of code, I will direct you towards graphing calculators in case you are unaware of such useful time savers. They would have solved your problem in the time it takes to enter the data (by copy&paste thats not very long)

Online graphing calculators example apps Geogebra and Desmos and many more.

这篇关于检测线条是否在Google图表或Plot.ly中相交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆