GLmol.prototype.render2d = function()

in gsoc2022/seagrid-rich-client/molview/src/js/lib/GLmol.js [2507:2708]


	GLmol.prototype.render2d = function()
	{
		var ctx = this.canvas2d[0].getContext("2d");
		this.scene.updateMatrixWorld();

		ctx.clearRect(0, 0, this.WIDTH, this.HEIGHT);
		ctx.fillStyle = "rgba(" + (this.bgColor >> 16) + "," + (this.bgColor >> 8 & 0xFF)
			+ "," + (this.bgColor & 0xFF) + "," + this.bgAlpha + ")";
		ctx.fillRect(0, 0, this.WIDTH, this.HEIGHT);
		ctx.save();

		ctx.translate(this.WIDTH / 2, this.HEIGHT / 2);
		ctx.scale(this.zoom2D || 1, this.zoom2D || 1);

		var lineWidth = 0.02;
		var mvMat = new THREE.Matrix4();
		mvMat.multiply(this.camera.matrixWorldInverse, this.modelGroup.matrixWorld);

		var PI2 = Math.PI * 2;
		var atoms = this.atoms;

		//transform coordinates
		for(var i = 0; i < this.atoms.length; i++)
		{
			var atom = atoms[i];
			if(atom == undefined) continue;

			if(atom.screen == undefined) atom.screen = new THREE.Vector3;
			atom.screen.set(atom.x, atom.y, atom.z);

			/*p*/
			mvMat.multiplyVector3(atom.screen);
			if(!this.webglFailed) atom.screen.y *= -1;//plus direction of y-axis: up in OpenGL, down in Canvas
		}

		//create draw stack
		if(this.canvasdrawStack.length == 0)
		{
			for(var i = 0; i < atoms.length; i++)
			{
				var atom = atoms[i];
				if(atom == undefined) continue;

				var part = {
					i: i,
					screen: atom.screen,
					color: "rgb(" + (atom.color >> 16) + "," + (atom.color >> 8 & 255) + "," + (atom.color & 255) + ")",
					r: this.canvasVDW ? GLmolVDWRadii[atom.elem] : this.canvasAtomRadius
				};

				//cache arc
				part.arc = [];
				if(part.r > 0)
				{
					var detail = this.canvasDetail;
					for(var v = 0; v < detail; v++)
					{
						part.arc.push([ part.r * Math.cos(PI2 / detail * v),
										part.r * Math.sin(PI2 / detail * v) ]);
					}
				}

				//add bonds
				part.bonds = [];
				for(var j = 0; j < atom.bonds.length; j++)
				{
					var atom2 = atoms[atom.bonds[j]];
					if(atom2 == undefined) continue;

					part.bonds.push(atom.bonds[j]);
				}

				this.canvasdrawStack.push(part);
			}
		}

		//sort draw stack
		this.canvasdrawStack.sort(function(a, b)
		{
			return a.screen.z - b.screen.z;
		});

		//prepare
		for(var i = 0; i < this.canvasdrawStack.length; i++)
		{
			atoms[this.canvasdrawStack[i].i].zIndex = i;
		}

		//draw
		for(var i = 0; i < this.canvasdrawStack.length; i++)
		{
			var part = this.canvasdrawStack[i];

			//draw atom black body
			if(!this.isDragging && part.r > 0)
			{
				ctx.save();
				ctx.translate(part.screen.x, part.screen.y);

				ctx.fillStyle = "#000000";
				ctx.lineWidth = lineWidth;
				ctx.beginPath();
				var mult = (part.r + lineWidth) / part.r;
				for(var v = 0; v < part.arc.length; v++)
				{
					if(v == 0) ctx.moveTo(mult * part.arc[v][0], mult * part.arc[v][1]);
					else ctx.lineTo(mult * part.arc[v][0], mult * part.arc[v][1]);
				}
				ctx.closePath();
				ctx.fill();

				ctx.restore();

				//draw bonds blackbody
				if(!this.canvasVDW)
				{
					for(var j = 0; j < part.bonds.length; j++)
					{
						var atom = atoms[part.bonds[j]];

						if(atom.screen.z > part.screen.z ||
						  (atom.screen.z == part.screen.z && atom.zIndex > atoms[part.i].zIndex))
						{
							var cx = (part.screen.x + atom.screen.x) / 2;
							var cy = (part.screen.y + atom.screen.y) / 2;

							ctx.lineWidth = ((this.isDragging || this.canvasLine) ?
								1 / this.zoom2D : this.canvasBondWidth) + lineWidth * 2;
							ctx.strokeStyle = "#000000";

							ctx.beginPath();
							ctx.moveTo(part.screen.x, part.screen.y);
							ctx.lineTo(cx, cy);
							ctx.closePath();
							ctx.stroke();

							ctx.beginPath();
							ctx.moveTo(atom.screen.x, atom.screen.y);
							ctx.lineTo(cx, cy);
							ctx.closePath();
							ctx.stroke();
						}
					}
				}
			}

			//draw colored bonds
			if(!this.canvasVDW || this.isDragging)
			{
				for(var j = 0; j < part.bonds.length; j++)
				{
					var atom = atoms[part.bonds[j]];
					var atomColor = this.canvasdrawStack[atoms[part.bonds[j]].zIndex].color;

					if(atom.screen.z > part.screen.z ||
					  (atom.screen.z == part.screen.z && atom.zIndex > atoms[part.i].zIndex))
					{
						var cx = (part.screen.x + atom.screen.x) / 2;
						var cy = (part.screen.y + atom.screen.y) / 2;

						ctx.lineWidth = (this.isDragging || this.canvasLine) ?
							1 / this.zoom2D : this.canvasBondWidth;

						ctx.strokeStyle = part.color;
						ctx.beginPath();
						ctx.moveTo(part.screen.x, part.screen.y);
						ctx.lineTo(cx, cy);
						ctx.closePath();
						ctx.stroke();

						ctx.strokeStyle = atomColor;
						ctx.beginPath();
						ctx.moveTo(atom.screen.x, atom.screen.y);
						ctx.lineTo(cx, cy);
						ctx.closePath();
						ctx.stroke();
					}
				}
			}

			//draw atom
			if(!this.isDragging && part.r > 0)
			{
				ctx.save();
				ctx.translate(part.screen.x, part.screen.y);

				ctx.fillStyle = part.color;
				ctx.beginPath();
				for(var v = 0; v < part.arc.length; v++)
				{
					if(v == 0) ctx.moveTo(part.arc[v][0], part.arc[v][1]);
					else ctx.lineTo(part.arc[v][0], part.arc[v][1]);
				}
				ctx.closePath();
				ctx.fill();

				ctx.restore();
			}
		}

		ctx.restore();
	};