JS判断第四个点是否在前三个点构成的三角形范围内

有时候,我们想判断一下第四个点是否在前面三个点构成的三角形范围内,可以参考以下的代码。



<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>已经有拉伸出来的正交投影模型,接下来要将中心转向面的选取和模型的平移,旋转,以及读取obj并显示模型</title>
	<style>
		.tabx{border-collapse:collapse;border-style: solid;border-width: 1px;text-align:center;}
		.tdx{border-style: solid;border-width: 1px;}

	</style>
</head>
<body>
<a><input type="file" id="selectFiles" onchange="dealSelectFiles()"  value="后续计划可以直接加载obj或gltf文件的模型" ></a>
<a><input type="button" id="btne"  value="拉伸" ></a>
<a><input type="button" id="btn"  value="保存" ></a>
<input type="text" id="txt" style="display:none;"/>
<div id="div" style="border:1px solid #000;"><canvas id="canvas"></canvas></div>
</br>

<script>
	var vShaderSource = 'attribute vec2 a_Position;'+
		'attribute vec2 a_Screen_Size;'+
		'uniform mat4 Pmatrix;'+
		'uniform mat4 Vmatrix;'+
		'uniform mat4 Mmatrix;'+
		'attribute vec3 color;'+//the color of the point
		'varying vec3 vColor;'+
		'void main(void) { '+//pre-built function
			//视图坐标(0~800,0~600)转换为 OPENGL坐标(-1.0,1.0)之间的值
			'vec2 xyposition = (a_Position / a_Screen_Size) * 2.0 - 1.0;'+
			'vec4 position=vec4(xyposition,0.0,1.0);'+
		   'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position);'+
		   'gl_PointSize = 10.0;'+
		   'vColor = color;'+
		'}';

	 var fShaderSource = 'precision mediump float;'+
		'varying vec3 vColor;'+
		'void main(void) {'+
		   'gl_FragColor = vec4(vColor, 1.);'+
		'}';
    let canvas = document.getElementById('canvas');
    canvas.width = window.innerWidth;//当前的宽度
    canvas.height = window.innerHeight;//当前的高度
    let gl = canvas.getContext('webgl');
    //创建顶点着色器
    let vShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vShader,vShaderSource);
    gl.compileShader(vShader);
    //创建片元着色器
    let fShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fShader,fShaderSource);
    gl.compileShader(fShader);
    //创建一个完整的着色器
    let propgram = gl.createProgram();
    gl.attachShader(propgram,vShader);
    gl.attachShader(propgram,fShader);
    gl.linkProgram(propgram);
    gl.useProgram(propgram);
    let positions =[];//设置一个数据
	let vectexs =[];//设置一个数据
	let x0=0;
	let y0=0;
    //设置缓冲区存放玩家点击的点的坐标
    let buffer = gl.createBuffer();
    //绑定缓冲区
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
    //取到我们需要使用的变量
    let a_Position = gl.getAttribLocation(propgram,'a_Position');
    gl.enableVertexAttribArray(a_Position);
    //每次取两个数据
    let size = 2;
    //每个数据的类型是32位浮点型
    let type = gl.FLOAT;
    //不需要归一化数据
    let normalize = false;
    // 每次迭代运行需要移动数据数 * 每个数据所占内存 到下一个数据开始点。
    let stride = 0;
    // 从缓冲起始位置开始读取
    let offset = 0;
    // 将 a_Position 变量获取数据的缓冲区指向当前绑定的 buffer。
    gl.vertexAttribPointer(a_Position, size, type, normalize, stride, offset)

    //片元色器
    let u_Color = gl.getAttribLocation(propgram,'color');
    gl.vertexAttrib3f(u_Color,0.0,0.0,1.0);

    //顶点着色器
    //处理顶点着色器中的变量
    let a_Screen_Size = gl.getAttribLocation(propgram,'a_Screen_Size');//取到屏幕的大小
    gl.vertexAttrib2f(a_Screen_Size,canvas.width,canvas.height);//设置参数
	//获取地址
	var _PM = gl.getUniformLocation(propgram, "Pmatrix");
	var _VM = gl.getUniformLocation(propgram, "Vmatrix");
	var _MM = gl.getUniformLocation(propgram, "Mmatrix");
	//正交投影
	var p_matrix = orth_projection(-1,1,-1,1,1,100);
	//模型举证
	var m_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];
	//视图矩阵
	var v_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];
	//绑定 
	gl.uniformMatrix4fv(_PM, false, p_matrix);
	gl.uniformMatrix4fv(_VM, false, v_matrix);
	gl.uniformMatrix4fv(_MM, false, m_matrix);		 
	//背景色
	gl.clearColor(1,1,1,1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    //捕获按钮事件
	var handler=function(e){
		var x = e.offsetX;
        var y = e.offsetY;
		positions .push(x,y);
		vectexs.push(x,y)
		if(positions.length == 2){
			x0=x;
			y0=y;
			gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
			gl.clearColor(1,1,1,1.0);
			gl.clear(gl.COLOR_BUFFER_BIT);
			gl.drawArrays(gl.POINTS, 0, positions.length / 2);
		}else if(vectexs.length<6)
		{
			positions .push(x,y);
			gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
            gl.clearColor(1,1,1,1.0);
			gl.clear(gl.COLOR_BUFFER_BIT);
			gl.drawArrays(gl.LINES, 0, positions.length / 2);
		}else if(vectexs.length==6)
		{
			positions .push(x,y);
			positions .push(x0,y0);
			gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
            gl.clearColor(1,1,1,1.0);
			gl.clear(gl.COLOR_BUFFER_BIT);
			gl.drawArrays(gl.LINES, 0, positions.length / 2);
		}else if(vectexs.length==8)
		{
			//判断第四个点是否在前三个点形成的三角形范围内
			//到最长边的垂直线和到其他两个边的垂直线的夹角都大于90度
			var PMax,Ver;
			var P1=Math.sqrt((vectexs[0]-vectexs[2])*(vectexs[0]-vectexs[2])+(vectexs[1]-vectexs[3])*(vectexs[1]-vectexs[3]));
			var P2=Math.sqrt((vectexs[2]-vectexs[4])*(vectexs[2]-vectexs[4])+(vectexs[3]-vectexs[5])*(vectexs[3]-vectexs[5]));
			var P3=Math.sqrt((vectexs[4]-vectexs[0])*(vectexs[4]-vectexs[0])+(vectexs[5]-vectexs[1])*(vectexs[5]-vectexs[1]));
			if(P1>P2){PMax=P1;Ver="0";}else{PMax=P2;Ver="2";}
			if(PMax<P3){PMax=P3;Ver="4";}

			var Vec1=new vec2(vectexs[0],vectexs[1]);
			var Vec2=new vec2(vectexs[2],vectexs[3]);
			var Vec3=new vec2(vectexs[4],vectexs[5]);
			var Vec4=new vec2(vectexs[6],vectexs[7]);
			//y=ax+b=>Vec1._y=a*Vec1._x+b;Vec2._y=a*Vec2._x+b;
			//=>   a=(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x);
			//=>   b=Vec1._y-(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)*Vec1._x
			//相互垂直的两条线的斜率乘积为-1;y=a1x+b1=>
			//=>   a1=-(Vec2._x-Vec1._x)/(Vec2._y-Vec1._y);
			//=>   b1=Vec4._y+(Vec2._x-Vec1._x)/(Vec2._y-Vec1._y)*Vec4._x
			//两条线的交点的坐标为(y=ax+b;y=a1x+b1   =>(a-a1)*x=b1-b   =>x=(b1-b)/(a-a1):
			var x12=-(Vec1._y-(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)*Vec1._x-Vec4._y-(Vec2._x-Vec1._x)/(Vec2._y-Vec1._y)*Vec4._x)/((Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)+(Vec2._x-Vec1._x)/(Vec2._y-Vec1._y));
			var y12=(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)*x12+Vec1._y-(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)*Vec1._x;
			
			var x23=-(Vec2._y-(Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)*Vec2._x-Vec4._y-(Vec3._x-Vec2._x)/(Vec3._y-Vec2._y)*Vec4._x)/((Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)+(Vec3._x-Vec2._x)/(Vec3._y-Vec2._y));
			var y23=(Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)*x23+Vec2._y-(Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)*Vec2._x;
			
			var x31=-(Vec3._y-(Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)*Vec3._x-Vec4._y-(Vec1._x-Vec3._x)/(Vec1._y-Vec3._y)*Vec4._x)/((Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)+(Vec1._x-Vec3._x)/(Vec1._y-Vec3._y));
			var y31=(Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)*x31+Vec3._y-(Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)*Vec3._x;
			//计算三条垂直线的矢量
			var nor1=new vec2(x12-Vec4._x,y12-Vec4._y)
			var nor2=new vec2(x23-Vec4._x,y23-Vec4._y)
			var nor3=new vec2(x31-Vec4._x,y31-Vec4._y)
			//根据点积公式算夹角
			var A1=vec2.angleBetween(nor1,nor2)/3.1415926*180;
			var A2=vec2.angleBetween(nor2,nor3)/3.1415926*180;
			var A3=vec2.angleBetween(nor3,nor1)/3.1415926*180;
			
			//目前的判断基本准确,可能在钝边三角形有时候判断出错,可能是因为第四个点落点问题
			if(Ver=="0")
			{
				console.log("最长的边为第一条边,边长为:"+PMax+";对应的两个角为:"+A1+","+A3);
				if(A1>=90&&A3>=90)
				{
					console.log("第四个点在三角形范围内。");
				}else
				{
					console.log("第四个点 不 在三角形范围内。");
				}
			}else if(Ver=="2")
			{
				console.log("最长的边为第二条边,边长为:"+PMax+";对应的两个角为:"+A1+","+A2);
				if(A1>=90&&A2>=90)
				{
					console.log("第四个点在三角形范围内。");
				}else
				{
					console.log("第四个点 不 在三角形范围内。");
				}
			}else if(Ver=="4")
			{
				console.log("最长的边为第三条边,边长为:"+PMax+";对应的两个角为:"+A2+","+A3);
				if(A2>=90&&A3>=90)
				{
					console.log("第四个点在三角形范围内。");
				}else
				{
					console.log("第四个点 不 在三角形范围内。");
				}
			}
		}
	};
	var handlerm=function(e){
		var x = e.offsetX;
        var y = e.offsetY;
		
		var PMax,Ver;
		var P1=Math.sqrt((vectexs[0]-vectexs[2])*(vectexs[0]-vectexs[2])+(vectexs[1]-vectexs[3])*(vectexs[1]-vectexs[3]));
		var P2=Math.sqrt((vectexs[2]-vectexs[4])*(vectexs[2]-vectexs[4])+(vectexs[3]-vectexs[5])*(vectexs[3]-vectexs[5]));
		var P3=Math.sqrt((vectexs[4]-vectexs[0])*(vectexs[4]-vectexs[0])+(vectexs[5]-vectexs[1])*(vectexs[5]-vectexs[1]));
		if(P1>P2){PMax=P1;Ver="0";}else{PMax=P2;Ver="2";}
		if(PMax<P3){PMax=P3;Ver="4";}
		var Vec1=new vec2(vectexs[0],vectexs[1]);
		var Vec2=new vec2(vectexs[2],vectexs[3]);
		var Vec3=new vec2(vectexs[4],vectexs[5]);
		var Vec4=new vec2(x,y);

		var x12=-(Vec1._y-(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)*Vec1._x-Vec4._y-(Vec2._x-Vec1._x)/(Vec2._y-Vec1._y)*Vec4._x)/((Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)+(Vec2._x-Vec1._x)/(Vec2._y-Vec1._y));
		var y12=(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)*x12+Vec1._y-(Vec2._y-Vec1._y)/(Vec2._x-Vec1._x)*Vec1._x;
		
		var x23=-(Vec2._y-(Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)*Vec2._x-Vec4._y-(Vec3._x-Vec2._x)/(Vec3._y-Vec2._y)*Vec4._x)/((Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)+(Vec3._x-Vec2._x)/(Vec3._y-Vec2._y));
		var y23=(Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)*x23+Vec2._y-(Vec3._y-Vec2._y)/(Vec3._x-Vec2._x)*Vec2._x;
		
		var x31=-(Vec3._y-(Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)*Vec3._x-Vec4._y-(Vec1._x-Vec3._x)/(Vec1._y-Vec3._y)*Vec4._x)/((Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)+(Vec1._x-Vec3._x)/(Vec1._y-Vec3._y));
		var y31=(Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)*x31+Vec3._y-(Vec1._y-Vec3._y)/(Vec1._x-Vec3._x)*Vec3._x;
		//计算三条垂直线的矢量
		var nor1=new vec2(x12-Vec4._x,y12-Vec4._y)
		var nor2=new vec2(x23-Vec4._x,y23-Vec4._y)
		var nor3=new vec2(x31-Vec4._x,y31-Vec4._y)
		//根据点积公式算夹角
		var A1=vec2.angleBetween(nor1,nor2)/3.1415926*180;
		var A2=vec2.angleBetween(nor2,nor3)/3.1415926*180;
		var A3=vec2.angleBetween(nor3,nor1)/3.1415926*180;
		
		//目前的判断基本准确,可能在钝边三角形有时候判断出错,可能是因为第四个点落点问题
		if(Ver=="0")
		{
			console.log("最长的边为第一条边,边长为:"+PMax+";对应的两个角为:"+A1+","+A3);
			if(A1>=90&&A3>=90)
			{
				console.log("第四个点在三角形范围内。");
			}else
			{
				console.log("第四个点 不 在三角形范围内。");
			}
		}else if(Ver=="2")
		{
			console.log("最长的边为第二条边,边长为:"+PMax+";对应的两个角为:"+A1+","+A2);
			if(A1>=90&&A2>=90)
			{
				console.log("第四个点在三角形范围内。");
			}else
			{
				console.log("第四个点 不 在三角形范围内。");
			}
		}else if(Ver=="4")
		{
			console.log("最长的边为第三条边,边长为:"+PMax+";对应的两个角为:"+A2+","+A3);
			if(A2>=90&&A3>=90)
			{
				console.log("第四个点在三角形范围内。");
			}else
			{
				console.log("第四个点 不 在三角形范围内。");
			}
		}
	};
	canvas.addEventListener('mouseup',handler,false);
	canvas.addEventListener('mousemove',handlerm,false);
	document.addEventListener('keydown',e=>{
		if(e.key=='c')
		{
			drawconvex();			
		}
	});
	//定义vec2类型
	function vec2(x,y){
		this._x = x;
		this._y = y;
	}
	vec2.angleBetween = function(v1,v2){
		if(!v1.isNormalized()){
		v1 = v1.clone().normalize();
		}

		if(!v2.isNormalized()){
		v2 = v2.clone().normalize();
		}

		return Math.acos(v1.dotProd(v2));
	};

	vec2.prototype = {
		setX : function(x){
		this._x = x;
		},
		getX : function(){
			return this._x;
		},
		setY : function(y){
		this._y = y;
		},
		getY : function(){
		return this._y;
		},
		clone : function(){
		return new vec2(this._x,this._y);
		},

		zero : function(){
		this._x = 0;
		this._y = 0;
		return this;
		},
		isZero : function(){
		return this._x == 0 && this._y == 0;
		},
		setLength : function(length){
		var angle = this.getAngle();
		this._x = Math.cos(angle) * length;
		this._y = Math.sin(angle) * length;
		},
		getLength : function(){
		return Math.sqrt(this.getLengthSQ());
		},
		getLengthSQ : function(){
		return this._x * this._x + this._y * this._y;
		},
		setAngle : function(angle){
		var length = this.getLength();
		this._x = Math.cos(angle) * length;
		this._y = Math.sin(angle) * length;
		},
		getAngle : function(){
		return Math.atan2(this._y,this._x);
		},
		normalize : function(){
		var length = this.getLength();
		if(length == 0){
		this._x = 1;
		return this;
		}
		this._x /= length;
		this._y /= length;
		return this;
		},
		isNormalized : function(){
		return this.getLength() == 1.0;
		},
		reverse : function(){
		this._x = -this._x;
		this._y = -this._y;
		return this;
		},
		dotProd : function(v2){
		return this._x * v2.getX() + this._y * v2.getY();
		},
		crossProd : function(v2){
		return this._x * v2.getY() - this._y * v2.getX();
		},
		getPerp : function(){
		return new vec2(-this._y,this._x);
		},
		sign : function(v2){
		return this.getPerp().dotProd(v2) < 0 ? -1 : 1;
		},
		dist : function(v2){
		return Math.sqrt(this.distSQ(v2));
		},
		distSQ : function(v2){
		var dx = v2.getX() - this._x;
		   dy = v2.getY() - this._y;
		return dx * dx + dy * dy;
		},
		add : function(v2){
		return new vec2(this._x + v2.getX(),this._y + this.getY());
		},
		subtract : function(v2){
		return new vec2(this._x - v2.getX(),this._y - v2.getY());
		},
		multiply : function(n){
		return new vec2(this._x * n,this._y * n);
		},
		divide : function(n){
		return new vec2(this._x / n,this._y / n);
		},
		equals : function(v2){
		return this._x == v2.getX() && this._y == v2.getY();
		}
	};
	function dealSelectFiles() {
		var file = document.getElementById("selectFiles").files[0];
		var name = file.name;//读取选中文件的文件名
		var path = document.getElementById("selectFiles").value;//读取选中文件的路径
		console.log("文件名:"+name+"大小:"+path);
		//获取读取我文件的File对象
		//alert(title:'hello',content:'success');
		var reader = new FileReader();//这是核心,读取操作就是由它完成.
		reader.readAsText(file,'UTF-8');//读取文件的内容,也可以读取文件的URL
		reader.onload = function (event) {
			//当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
			document.getElementById("txt").value =event.target.result;
			document.getElementById("txt").style.display="block";
		}
	}
	
	function drawconvex()
	{
		console.log(vectexs.length);
	}
	function ExtrudeShape()
	{
		positions.push(x0,y0);
		var pos=[];
		var poss=[]
		for(var m=0;m<positions.length/2;m++)
		{
			pos=[positions[2*m],positions[2*m+1]];
			poss.push(pos);
		}
		if(convex(poss,positions.length)==1)
		{
			//alert("凸集");
			gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
			this.show(gl);
			//vertexs里面存储了所有顶点的信息,可以利用来拉伸出立方体
			//如P1,P2,P3,P4,P5,P6;先画P1,P2,P3;P1,P3,P4;P1,P4,P5;P1,P5,P6四个三角形
			//再画对面P11,P12,P13;P11,P13,P14;P11,P14,P15;P11,P15,P16四个三角形
			//再画旁边P1,P2,P11;P12,P2,P11;P2,P3,P12;P13,P3,P12;P3,P4,P13;P14,P4,P13;
			//P4,P5,P14;P15,P5,P14;P5,P6,P15;P16,P6,P15;P6,P1,P16;P11,P1,P16;十二个三角形

			var vers =[];
			var cors=[];
			for(var m=0;m<vectexs.length/2;m++)
			{
				vers.push(vectexs[2*m],vectexs[2*m+1],-100);
				cors.push(1/(m+1),0,1);
				vers.push(vectexs[2*m],vectexs[2*m+1],100);
				cors.push(1/(m+1),1,0);
			}
			var inds=[];
			//准备顶点的顺序
			for(var m=1;m<vers.length/6-1;m++)
			{
				inds.push(0,2*m,2*m+2);
			}
			var btm=vers.length/3;
			for(var m=0;m<vers.length/6;m++)
			{
				inds.push(2*m % btm,(2*m+1) % btm,(2*m+2)% btm);
				inds.push((2*m+1)% btm,(2*m+2)% btm,(2*m+3)% btm);
			}
			for(var m=1;m<vers.length/6-1;m++)
			{
				inds.push(1,2*m+1,2*m+3);
			}
			
			var _Pmatrix;
			var _Vmatrix;
			var _Mmatrix;
			var index_buffer;

			// Create and store data into vertex buffer
			 var vertex_buffer = gl.createBuffer ();
			 gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
			 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vers), gl.STATIC_DRAW);

			 // Create and store data into color buffer
			 var color_buffer = gl.createBuffer ();
			 gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
			 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cors), gl.STATIC_DRAW);

			 // Create and store data into index buffer
			 //attribute变量和uniform变量,一次只能传输一个顶点的信息
			 //缓冲区对象可以一次性的向着色器传入多个顶点的数据
			 //步骤一:创建buffer
			 index_buffer = gl.createBuffer ();
			 //步骤二:绑定buffer
			 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
			 //步骤三:数据写入buffer
			 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(inds), gl.STATIC_DRAW);
												  
			 /*=================== SHADERS =================== */

			 var vertCode = 'attribute vec3 position;'+
				'attribute vec3 a_Screen_Size;'+
				'uniform mat4 Pmatrix;'+
				'uniform mat4 Vmatrix;'+
				'uniform mat4 Mmatrix;'+
				'attribute vec3 color;'+//the color of the point
				'varying vec3 vColor;'+
				'void main(void) { '+//pre-built function
					'vec3 outposition = (position / a_Screen_Size) * 2.0 - 1.0;'+
				   'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(outposition, 1.0);'+
				   'vColor = color;'+
				'}';

			 var fragCode = 'precision mediump float;'+
				'varying vec3 vColor;'+
				'void main(void) {'+
				   'gl_FragColor = vec4(vColor, 1.);'+
				'}';

			 var vertShader = gl.createShader(gl.VERTEX_SHADER);
			 gl.shaderSource(vertShader, vertCode);
			 gl.compileShader(vertShader);

			 var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
			 gl.shaderSource(fragShader, fragCode);
			 gl.compileShader(fragShader);
				
			 var shaderprogram = gl.createProgram();
			 gl.attachShader(shaderprogram, vertShader);
			 gl.attachShader(shaderprogram, fragShader);
			 gl.linkProgram(shaderprogram);
			 
			 var a_Screen_Size = gl.getAttribLocation(propgram,'a_Screen_Size');//取到屏幕的大小
			 gl.vertexAttrib3f(a_Screen_Size,canvas.width,canvas.height,100);//设置参数
			 
			 /*======== Associating attributes to vertex shader =====*/
			 _Pmatrix = gl.getUniformLocation(shaderprogram, "Pmatrix");
			 _Vmatrix = gl.getUniformLocation(shaderprogram, "Vmatrix");
			 _Mmatrix = gl.getUniformLocation(shaderprogram, "Mmatrix");

			 gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
			 var _position = gl.getAttribLocation(shaderprogram, "position");
			 //步骤四:buffer对象分配给一个attribute变量
			 gl.vertexAttribPointer(_position, 3, gl.FLOAT, false,0,0);
			 //步骤五:开启attribute变量
			 gl.enableVertexAttribArray(_position);

			 gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
			 var _color = gl.getAttribLocation(shaderprogram, "color");
			 gl.vertexAttribPointer(_color, 3, gl.FLOAT, false,0,0) ;
			 gl.enableVertexAttribArray(_color);
			 gl.useProgram(shaderprogram);
			
			 
			 //透视矩阵
			 //40-y方向视角,canvas.width/canvas.height-宽高比,1-Znear,100-Zfar
			 //var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);
			 //正交投影
			 var proj_matrix = orth_projection(-1,1,-1,1,1,100);
			 //模型举证
			 var mo_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];
			 //视图矩阵
			 var view_matrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ];

			 view_matrix[14] = view_matrix[14]-6;

			
			 /*================= Mouse events ======================*/

			 var AMORTIZATION = 0.95;
			 var drag = false;
			 var old_x, old_y;
			 var dX = 0, dY = 0;
			 var THETA = 0,
			 PHI = 0;
			 var time_old = 0;
			 var mouseDown = function(e) {
				drag = true;
				old_x = e.pageX, old_y = e.pageY;
				console.log(e.pageX+"_"+e.pageY);
				//要搞清楚每一个三角形在屏幕上的点的坐标
				//然后判断点的坐标是否在三角形内
				e.preventDefault();
				return false;
			 };
			 
			 var mouseUp = function(e){
				drag = false;
			 };
			 
			 var mouseMove = function(e) {
				//1.先计算三角形的三条边长
				//2.计算出点击点到三条边的法向矢量
				//3.如果到最长边的法向矢量和另外2个法向矢量的夹角都大于90度(小于180),点在三角形内部,否则在三角形外面
				dX = (e.pageX-old_x)*2*Math.PI/canvas.width,
				dY = (e.pageY-old_y)*2*Math.PI/canvas.height;
				THETA+= dX;
				PHI+=dY;
				old_x = e.pageX, old_y = e.pageY;
				e.preventDefault();
			 };
			 canvas.removeEventListener('mouseup',handler,false);
			 canvas.addEventListener("mousedown", mouseDown, false);
			 canvas.addEventListener("mouseup", mouseUp, false);
			 canvas.addEventListener("mouseout", mouseUp, false);
			 canvas.addEventListener("mousemove", mouseMove, false);
			 var animate = function(time) {
				var dt = time-time_old;
						
				if (!drag) {
				   dX *= AMORTIZATION, dY*=AMORTIZATION;
				   THETA+=dX, PHI+=dY;
				}
				   
				//set model matrix to I4
						
				mo_matrix[0] = 1, mo_matrix[1] = 0, mo_matrix[2] = 0,
				mo_matrix[3] = 0,
						
				mo_matrix[4] = 0, mo_matrix[5] = 1, mo_matrix[6] = 0,
				mo_matrix[7] = 0,
						
				mo_matrix[8] = 0, mo_matrix[9] = 0, mo_matrix[10] = 1,
				mo_matrix[11] = 0,
						
				mo_matrix[12] = 0, mo_matrix[13] = 0, mo_matrix[14] = 0,
				mo_matrix[15] = 1;

				rotateY(mo_matrix, THETA);
				rotateX(mo_matrix, PHI);
						
				time_old = time; 
				gl.enable(gl.DEPTH_TEST);
						
				// gl.depthFunc(gl.LEQUAL);
						
				gl.clearColor(1, 1, 1, 0.9);
				gl.clearDepth(1.0);
				gl.viewport(0.0, 0.0, canvas.width, canvas.height);
				gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

				gl.uniformMatrix4fv(_Pmatrix, false, proj_matrix);
				gl.uniformMatrix4fv(_Vmatrix, false, view_matrix);
				gl.uniformMatrix4fv(_Mmatrix, false, mo_matrix);
				//绑定index_buffer
				gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
				//用index_buffer中的顶点画模型
				gl.drawElements(gl.TRIANGLES, inds.length, gl.UNSIGNED_SHORT, 0);
						
				window.requestAnimationFrame(animate);
			 }
				
			 animate(0);
		}else if(convex(poss,positions.length)==-1)
		{
			alert("凹集");
		}else if(convex(poss,positions.length)==0)
		{
			alert("曲线不符合要求,无法计算");
		}
	}
	const buttonext = document.getElementById('btne');
	buttonext.onclick = () => {
		drawconvex();
	}
	// 获取按钮
	const button = document.getElementById('btn')
	// 给按钮添加点击事件
	button.onclick = () => {
		// 要保存的字符串
		var stringData ='您输入的坐标是:';
		for(var m=0;m<vectexs.length;m++)
		{
			if(m % 2==1)
			{
				stringData=stringData+vectexs[m]+";";
			}else
			{
				stringData=stringData+vectexs[m]+"-";
			}
		}

		// dada 表示要转换的字符串数据,type 表示要转换的数据格式
		const blob = new Blob([stringData], {
			type: "text/plain;charset=utf-8"
		})
		// 根据 blob生成 url链接
		const objectURL = URL.createObjectURL(blob)

		// 创建一个 a 标签Tag
		const aTag = document.createElement('a')
		// 设置文件的下载地址
		aTag.href = objectURL
		// 设置保存后的文件名称
		aTag.download = "文本文件.txt"
		// 给 a 标签添加点击事件
		document.body.appendChild(aTag)
		let evt = document.createEvent("MouseEvents");
		evt.initEvent("click", true, true);
		aTag.dispatchEvent(evt);
		document.body.removeChild(aTag);
	}
	/*=========================rotation================*/

	 function rotateX(m, angle) {
		var c = Math.cos(angle);
		var s = Math.sin(angle);
		var mv1 = m[1], mv5 = m[5], mv9 = m[9];
			
		m[1] = m[1]*c-m[2]*s;
		m[5] = m[5]*c-m[6]*s;
		m[9] = m[9]*c-m[10]*s;

		m[2] = m[2]*c+mv1*s;
		m[6] = m[6]*c+mv5*s;
		m[10] = m[10]*c+mv9*s;
	 }

	 function rotateY(m, angle) {
		var c = Math.cos(angle);
		var s = Math.sin(angle);
		var mv0 = m[0], mv4 = m[4], mv8 = m[8];
			
		m[0] = c*m[0]+s*m[2];
		m[4] = c*m[4]+s*m[6];
		m[8] = c*m[8]+s*m[10];

		m[2] = c*m[2]-s*mv0;
		m[6] = c*m[6]-s*mv4;
		m[10] = c*m[10]-s*mv8;
	 }
	function orth_projection(Lpos,Rpos,Tpos,Bpos,Znear,Zfar)
	{
		return [2/(Rpos-Lpos),0,0,0,
		0,2/(Tpos-Bpos),0,0,
		0,0,1/(Zfar-Znear),0,
		-(Rpos+Lpos)/(Rpos-Lpos),-(Tpos+Bpos)/(Tpos-Bpos),-Znear/(Zfar-Znear),1];
	}
	function get_projection(angle, a, zMin, zMax) {
		var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
		return [
		   1/ang/a, 0 , 0, 0,
		   0, 1/ang, 0, 0,
		   0, 0, -(zMax+zMin)/(zMax-zMin), -1,
		   0, 0, (-2*zMax*zMin)/(zMax-zMin), 0 
		   ];
	 }
	
	function abs(x,y)
	{
		if(x>y)
		{
			return x-y;
		}else
		{
			return y-x;
		}
	}
	function circle()
	{
		alert("Hi");
		//r*cos(60*m),r*sin(60*m)
	}

	function convex(p,n){
		var j,k,z;
		var flag=0;
		if(n<3){
			return 0;
		}
		for(var i=0;i<n/2-1;i++)
		{
			j=(i+1)%(n/2-1);
			k=(i+2)%(n/2-1);
			z=(p[j][0]-p[i][0])*(p[k][1]-p[j][1]);
			z-=(p[j][1]-p[i][1])*(p[k][0]-p[j][0]);
			if(z<0)
			{
				flag|=1;
			}else if(z>0)
			{
				flag|=2;
			}
			if(flag==3)
			{
				return -1;
			}
		}
		if(flag!=0)
		{
			return 1;
		}else
		{
			return 0;
		}
	}
    // this.show(gl);
    function  show(gl) {
        gl.clearColor(1,1,1,1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawArrays(gl.LINES, 0, positions.length / 2);
    }

    //随机取到相关的颜色

    function randomColor() {
        return {
            r: Math.random() * 255,
            g: Math.random() * 255,
            b: Math.random() * 255,
            a: 1 * 1
        };
    } 

</script>
</body>
</html>

将以上代码保存到一个html文件里面,在浏览其中打开文件,就可以看到效果了。

备注:代码已升级,鼠标在桌面移动时,会看到鼠标所在的点是否在三角形范围内。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水滴与鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值