Clazz.declarePackage("J.renderspecial");
Clazz.load(["J.render.MeshRenderer", "JU.BS", "$.P3", "$.P3i", "$.V3"], "J.renderspecial.DrawRenderer", ["JU.A4", "$.M3", "$.Measure", "J.shapespecial.Draw", "JU.C", "$.GData"], function(){
var c$ = Clazz.decorateAsClass(function(){
this.drawType = null;
this.dmesh = null;
this.controlHermites = null;
this.pt0 = null;
this.pt1 = null;
this.pt2 = null;
this.vTemp = null;
this.vTemp2 = null;
this.headFactor = 0;
this.pt0f = null;
this.pt0i = null;
this.s0f = null;
this.s1f = null;
this.s2f = null;
this.bsHandles = null;
this.haveNotifiedHandles = false;
Clazz.instantialize(this, arguments);}, J.renderspecial, "DrawRenderer", J.render.MeshRenderer);
Clazz.prepareFields (c$, function(){
this.pt0 =  new JU.P3();
this.pt1 =  new JU.P3();
this.pt2 =  new JU.P3();
this.vTemp =  new JU.V3();
this.vTemp2 =  new JU.V3();
this.pt0f =  new JU.P3();
this.pt0i =  new JU.P3i();
this.bsHandles =  new JU.BS();
});
Clazz.overrideMethod(c$, "render", 
function(){
this.needTranslucent = false;
this.imageFontScaling = this.vwr.imageFontScaling;
var draw = this.shape;
for (var i = 0, n = draw.meshCount; i < n; i++) {
var mesh = this.dmesh = draw.meshes[i];
if (mesh == null || this.dmesh.drawType == null) {
return false;
}if (this.dmesh.thisModelOnly && this.vwr.am.cmi < 0) continue;
if (mesh.connectedAtoms != null) {
if (mesh.connectedAtoms[0] < 0) continue;
mesh.vs =  new Array(4);
mesh.vc = 4;
var c = mesh.connectedAtoms;
for (var j = 0; j < 4; j++) mesh.vs[j] = (c[j] < 0 ? mesh.vs[j - 1] : this.vwr.ms.at[c[j]]);

mesh.recalcAltVertices = true;
}if (this.renderMesh2(mesh)) this.renderInfo();
if (!this.isExport && mesh.visibilityFlags != 0 && (this.vwr.getDrawHover() || this.vwr.getPickingMode() == 4)) {
if (!this.g3d.setC(JU.C.getColixTranslucent3(23, true, 0.5))) this.needTranslucent = true;
 else this.renderHandles();
}}
return this.needTranslucent;
});
Clazz.overrideMethod(c$, "isPolygonDisplayable", 
function(i){
return J.shapespecial.Draw.isPolygonDisplayable(this.dmesh, i) && (this.dmesh.modelFlags == null || this.dmesh.bsMeshesVisible.get(i));
}, "~N");
Clazz.overrideMethod(c$, "render2", 
function(isExport){
this.drawType = this.dmesh.drawType;
this.diameter = this.dmesh.diameter;
this.width = this.dmesh.width;
this.headFactor = (this.diameter != 0 && this.width != 0 ? this.diameter : 0);
if (this.mesh.connectedAtoms != null) this.getConnectionPoints();
if (this.mesh.lineData != null) {
this.drawLineData(this.mesh.lineData);
return;
}var nPoints = this.vertexCount;
var isArrow = this.drawType === J.shapespecial.Draw.EnumDrawType.ARROW;
var isCurved = ((isArrow || this.drawType === J.shapespecial.Draw.EnumDrawType.CURVE || this.drawType === J.shapespecial.Draw.EnumDrawType.ARC) && this.vertexCount > 2);
if (this.width > 0 && isCurved || isArrow) {
this.pt1f.set(0, 0, 0);
var n = (this.drawType === J.shapespecial.Draw.EnumDrawType.ARC ? 2 : this.vertexCount);
for (var i = 0; i < n; i++) this.pt1f.add(this.vertices[i]);

this.pt1f.scale(1 / n);
this.tm.transformPtScr(this.pt1f, this.pt1i);
this.diameter = Clazz.floatToInt(this.vwr.tm.scaleToScreen(this.pt1i.z, Clazz.doubleToInt(Math.floor(this.width * 1000))));
if (this.diameter == 0) this.diameter = 1;
}if (this.dmesh.haveXyPoints && this.drawXYPoints()) return;
var tension = 5;
switch (this.drawType) {
case J.shapespecial.Draw.EnumDrawType.CYLINDER:
this.allowDashed = false;
default:
this.render2b(false);
return;
case J.shapespecial.Draw.EnumDrawType.CIRCULARPLANE:
if (this.dmesh.scale > 0) this.width *= this.dmesh.scale;
this.allowDashed = false;
this.render2b(false);
return;
case J.shapespecial.Draw.EnumDrawType.CIRCLE:
this.tm.transformPtScr(this.vertices[0], this.pt1i);
if (this.diameter == 0 && this.width == 0) this.width = 1.0;
if (this.dmesh.scale > 0) this.width *= this.dmesh.scale;
if (this.width > 0) this.diameter = Clazz.floatToInt(this.vwr.tm.scaleToScreen(this.pt1i.z, Clazz.doubleToInt(Math.floor(this.width * 1000))));
if (this.diameter > 0 && (this.mesh.drawTriangles || this.mesh.fillTriangles)) {
this.g3d.addRenderer(1073741880);
this.g3d.drawFilledCircle(this.colix, this.mesh.fillTriangles ? this.colix : 0, this.diameter, this.pt1i.x, this.pt1i.y, this.pt1i.z);
}return;
case J.shapespecial.Draw.EnumDrawType.LINE_SEGMENT:
for (var i = 0; i < nPoints - 1; i++) this.drawEdge(i, i + 1, true, this.vertices[i], this.vertices[i + 1], this.screens[i], this.screens[i + 1]);

return;
case J.shapespecial.Draw.EnumDrawType.CURVE:
break;
case J.shapespecial.Draw.EnumDrawType.ARC:
var ptRef = (this.vertexCount > 2 ? this.vertices[2] : J.shapespecial.Draw.randomPoint());
var nDegreesOffset = (this.vertexCount > 3 ? this.vertices[3].x : 0);
var theta = (this.vertexCount > 3 ? this.vertices[3].y : 360);
if (theta == 0) return;
var fractionalOffset = (this.vertexCount > 3 ? this.vertices[3].z : 0);
nPoints = this.setArc(this.vertices[0], this.vertices[1], ptRef, nDegreesOffset, theta, fractionalOffset, this.dmesh.scale);
if (this.dmesh.isVector && !this.dmesh.noHead) {
this.renderArrowWithHead(this.pt0, this.pt1, 0.3, false, false, this.dmesh.isBarb);
this.tm.transformPtScr(this.pt1f, this.screens[nPoints - 1]);
this.tm.transformPtScrT3(this.pt1f, this.p3Screens[nPoints - 1]);
}this.pt1f.setT(this.pt2);
break;
case J.shapespecial.Draw.EnumDrawType.ARROW:
if (!isCurved) {
this.renderArrowWithHead(this.vertices[0], this.vertices[1], 0, false, true, this.dmesh.isBarb);
return;
}var nHermites = 5;
if (this.controlHermites == null || this.controlHermites.length < nHermites + 1) {
this.controlHermites =  new Array(nHermites + 1);
}JU.GData.getHermiteList(tension, this.vertices[this.vertexCount - 3], this.vertices[this.vertexCount - 2], this.vertices[this.vertexCount - 1], this.vertices[this.vertexCount - 1], this.vertices[this.vertexCount - 1], this.controlHermites, 0, nHermites, true);
this.renderArrowWithHead(this.controlHermites[nHermites - 2], this.controlHermites[nHermites - 1], 0, false, false, this.dmesh.isBarb);
break;
}
if (this.diameter == 0) this.diameter = 3;
if (isCurved) {
this.g3d.addRenderer(553648143);
for (var i = 0, i0 = 0; i < nPoints - 1; i++) {
this.g3d.fillHermite(tension, this.diameter, this.diameter, this.diameter, this.p3Screens[i0], this.p3Screens[i], this.p3Screens[i + 1], this.p3Screens[i + (i == nPoints - 2 ? 1 : 2)]);
i0 = i;
}
} else {
this.render2b(false);
}}, "~B");
Clazz.defineMethod(c$, "drawXYPoints", 
function(){
if (this.dmesh.isVector) {
var ptXY = 0;
for (var i = 0; i < 2; i++) if (J.shapespecial.Draw.is2DPoint(this.vertices[i])) ptXY += i + 1;

if (--ptXY < 2) {
this.renderXyArrow(ptXY);
return true;
}} else if (this.drawType === J.shapespecial.Draw.EnumDrawType.POINT || this.drawType === J.shapespecial.Draw.EnumDrawType.MULTIPLE) {
this.renderXyPoint();
return true;
}return false;
});
Clazz.defineMethod(c$, "setArc", 
function(v1, v2, ptRef, nDegreesOffset, theta, fractionalOffset, scale){
this.vTemp.sub2(v2, v1);
this.pt1f.scaleAdd2(fractionalOffset, this.vTemp, v1);
var mat =  new JU.M3().setAA(JU.A4.newVA(this.vTemp, (nDegreesOffset * 3.141592653589793 / 180)));
this.vTemp2.sub2(ptRef, v1);
this.vTemp2.cross(this.vTemp, this.vTemp2);
this.vTemp2.cross(this.vTemp2, this.vTemp);
this.vTemp2.normalize();
this.vTemp2.scale(scale / 2);
mat.rotate(this.vTemp2);
var degrees = theta / 5;
while (Math.abs(degrees) > 5) degrees /= 2;

var nPoints = Math.round(theta / degrees) + 1;
while (nPoints < 10) {
degrees /= 2;
nPoints = Math.round(theta / degrees) + 1;
}
mat.setAA(JU.A4.newVA(this.vTemp, (degrees * 3.141592653589793 / 180)));
this.screens = this.vwr.allocTempScreens(nPoints);
this.p3Screens = this.vwr.allocTempPoints(nPoints);
var iBase = nPoints - (this.dmesh.scale < 2 ? 3 : 3);
for (var i = 0; i < nPoints; i++) {
if (i == iBase) this.pt0.setT(this.pt1);
this.pt1.scaleAdd2(1, this.vTemp2, this.pt1f);
if (i == 0) this.pt2.setT(this.pt1);
this.tm.transformPtScr(this.pt1, this.screens[i]);
this.tm.transformPtScrT3(this.pt1, this.p3Screens[i]);
mat.rotate(this.vTemp2);
}
return nPoints;
}, "JU.T3,JU.T3,JU.T3,~N,~N,~N,~N");
Clazz.defineMethod(c$, "getConnectionPoints", 
function(){
this.vertexCount = 3;
var dmax = 3.4028235E38;
var i0 = 0;
var j0 = 0;
for (var i = 0; i < 2; i++) for (var j = 2; j < 4; j++) {
var d = this.vertices[i].distance(this.vertices[j]);
if (d < dmax) {
dmax = d;
i0 = i;
j0 = j;
}}

this.pt0.ave(this.vertices[0], this.vertices[1]);
this.pt2.ave(this.vertices[2], this.vertices[3]);
this.pt1.ave(this.pt0, this.pt2);
this.vertices[3] = JU.P3.newP(this.vertices[i0]);
this.vertices[3].add(this.vertices[j0]);
this.vertices[3].scale(0.5);
this.vertices[1] = JU.P3.newP(this.pt1);
this.vertices[0] = JU.P3.newP(this.pt0);
this.vertices[2] = JU.P3.newP(this.pt2);
for (var i = 0; i < 4; i++) this.tm.transformPtScr(this.vertices[i], this.screens[i]);

var f = 4 * this.getArrowScale();
var endoffset = 0.2;
var offsetside = (this.width == 0 ? 0.1 : this.width);
this.pt0.set(this.screens[0].x, this.screens[0].y, this.screens[0].z);
this.pt1.set(this.screens[1].x, this.screens[1].y, this.screens[1].z);
this.pt2.set(this.screens[3].x, this.screens[3].y, this.screens[3].z);
var dx = (this.screens[1].x - this.screens[0].x) * f;
var dy = (this.screens[1].y - this.screens[0].y) * f;
if (dmax == 0 || JU.Measure.computeTorsion(this.pt2, this.pt0, JU.P3.new3(this.pt0.x, this.pt0.y, 10000), this.pt1, false) > 0) {
dx = -dx;
dy = -dy;
}this.pt2.set(dy, -dx, 0);
this.pt1.add(this.pt2);
this.tm.unTransformPoint(this.pt1, this.vertices[1]);
this.pt2.scale(offsetside);
this.vTemp.sub2(this.vertices[1], this.vertices[0]);
this.vTemp.scale(endoffset);
this.vertices[0].add(this.vTemp);
this.vTemp.sub2(this.vertices[1], this.vertices[2]);
this.vTemp.scale(endoffset);
this.vertices[2].add(this.vTemp);
for (var i = 0; i < 3; i++) {
this.tm.transformPtScr(this.vertices[i], this.screens[i]);
if (offsetside != 0) {
this.screens[i].x += Math.round(this.pt2.x);
this.screens[i].y += Math.round(this.pt2.y);
this.pt1.set(this.screens[i].x, this.screens[i].y, this.screens[i].z);
this.tm.unTransformPoint(this.pt1, this.vertices[i]);
}}
});
Clazz.defineMethod(c$, "drawLineData", 
function(lineData){
if (this.diameter == 0) this.diameter = 3;
for (var i = lineData.size(); --i >= 0; ) {
var pts = lineData.get(i);
this.tm.transformPtScr(pts[0], this.pt1i);
this.tm.transformPtScr(pts[1], this.pt2i);
this.drawEdge(-1, -2, true, pts[0], pts[1], this.pt1i, this.pt2i);
}
}, "JU.Lst");
Clazz.defineMethod(c$, "renderXyPoint", 
function(){
var f = (this.g3d.isAntialiased() ? 2 : 1);
this.pt0.setT(this.vertices[0]);
if (this.diameter == 0) this.diameter = Clazz.floatToInt(this.width);
if (this.pt0.z == -3.4028235E38) {
this.pt0.x *= this.vwr.tm.width / 100;
this.pt0.y *= this.vwr.tm.height / 100;
this.diameter = Clazz.floatToInt(this.diameter * this.vwr.getScreenDim() / 100);
}this.diameter *= f;
this.pt1i.set(Clazz.floatToInt(this.pt0.x), Clazz.floatToInt(this.vwr.tm.height - this.pt0.y), Clazz.floatToInt(this.vwr.tm.cameraDistance));
this.g3d.fillSphereI(this.diameter, this.pt1i);
});
Clazz.defineMethod(c$, "renderXyArrow", 
function(ptXY){
var ptXYZ = 1 - ptXY;
var arrowPt =  new Array(2);
arrowPt[ptXYZ] = this.pt1;
arrowPt[ptXY] = this.pt0;
this.pt0.set(this.screens[ptXY].x, this.screens[ptXY].y, this.screens[ptXY].z);
this.tm.rotatePoint(this.vertices[ptXYZ], this.pt1);
this.pt1.z *= -1;
var zoomDimension = this.vwr.getScreenDim();
var scaleFactor = zoomDimension / 20;
this.pt1.scaleAdd2(this.dmesh.scale * scaleFactor, this.pt1, this.pt0);
if (this.diameter == 0) this.diameter = 1;
if (this.diameter < 0) this.g3d.drawDashedLineBits(8, 4, this.pt0, this.pt1);
 else this.g3d.fillCylinderBits(2, this.diameter, this.pt0, this.pt1);
this.renderArrowWithHead(this.pt0, this.pt1, 0, true, false, false);
}, "~N");
Clazz.defineMethod(c$, "renderArrowWithHead", 
function(pt1, pt2, factor2, isTransformed, withShaft, isBarb){
if (this.dmesh.noHead && !withShaft) return;
if (this.s0f == null) {
this.s0f =  new JU.P3();
this.s1f =  new JU.P3();
this.s2f =  new JU.P3();
}var fScale = this.getArrowScale();
if (isTransformed) fScale *= 40;
if (factor2 > 0) fScale *= factor2;
this.pt0f.setT(pt1);
this.pt2f.setT(pt2);
var d = this.pt0f.distance(this.pt2f);
if (d == 0) return;
var isNegScale = (fScale < 0);
var headScale = (this.headFactor == 0 && fScale < 0 ? -fScale : 1);
if (fScale < 0) fScale = -fScale;
var headWidth = (this.width > 0 && !this.dmesh.noHead ? this.width * headScale * 3 : 0);
this.vTemp.sub2(this.pt2f, this.pt0f);
this.vTemp.normalize();
this.vTemp.scale((this.headFactor > 0 ? this.headFactor * this.width : Math.min(headWidth == 0 ? fScale : headWidth * 1.5, fScale)) / 5);
if (!withShaft) this.pt2f.add(this.vTemp);
this.vTemp.scale(5);
var len = this.vTemp.length();
if (len > headWidth * 1.5) this.vTemp.scale(headWidth * 1.5 / len);
this.pt1f.sub2(this.pt2f, this.vTemp);
if (isTransformed) {
this.s1f.setT(this.pt1f);
this.s2f.setT(this.pt2f);
} else {
this.tm.transformPtScrT3(this.pt2f, this.s2f);
this.tm.transformPtScrT3(this.pt1f, this.s1f);
this.tm.transformPtScrT3(this.pt0f, this.s0f);
}if (this.s2f.z == 1 || this.s1f.z == 1) return;
var headDiameter;
if (this.diameter > 0) {
headDiameter = Clazz.floatToInt(this.diameter * headScale * 3);
} else {
this.vTemp.set(this.s2f.x - this.s1f.x, this.s2f.y - this.s1f.y, this.s2f.z - this.s1f.z);
headDiameter = Math.round(this.vTemp.length() * .5);
this.diameter = Clazz.doubleToInt(headDiameter / 5);
}if (this.diameter < 1) this.diameter = 1;
if (headDiameter > 2 && !this.dmesh.noHead) this.g3d.fillConeScreen3f(2, headDiameter, this.s1f, this.s2f, isBarb);
if (withShaft) this.g3d.fillCylinderScreen3I(2, this.diameter, this.s0f, this.s1f, null, null, 0);
}, "JU.T3,JU.T3,~N,~B,~B,~B");
Clazz.defineMethod(c$, "getArrowScale", 
function(){
var fScale = (this.dmesh.isScaleSet ? this.dmesh.scale : 0);
if (fScale == 0) fScale = this.vwr.getFloat(570425352) * (this.dmesh.connectedAtoms == null ? 1 : 0.5);
return fScale;
});
Clazz.defineMethod(c$, "renderHandles", 
function(){
var diameter = Math.round(10 * this.imageFontScaling);
switch (this.drawType) {
case J.shapespecial.Draw.EnumDrawType.NONE:
return;
default:
var colixFill = JU.C.getColixTranslucent3(23, true, 0.5);
this.bsHandles.clearAll();
this.g3d.addRenderer(1073741880);
for (var i = this.dmesh.pc; --i >= 0; ) {
if (!this.isPolygonDisplayable(i)) continue;
var vertexIndexes = this.dmesh.pis[i];
if (vertexIndexes == null) continue;
for (var j = (this.dmesh.isDrawPolygon ? 3 : vertexIndexes.length); --j >= 0; ) {
var k = vertexIndexes[j];
if (this.bsHandles.get(k)) continue;
this.bsHandles.set(k);
if (k >= this.screens.length) {
if (!this.haveNotifiedHandles) {
System.out.println("DrawRender handles k >= screens.length " + k + " ");
this.haveNotifiedHandles = true;
}} else {
this.g3d.drawFilledCircle(23, colixFill, diameter, this.screens[k].x, this.screens[k].y, this.screens[k].z);
}}
}
break;
}
});
Clazz.defineMethod(c$, "renderInfo", 
function(){
if (this.isExport || this.mesh.title == null || this.vwr.getDrawHover() || !this.g3d.setC(this.vwr.cm.colixBackgroundContrast)) return;
var f0 = this.vwr.shm.getShapePropertyIndex(22, "font", -1);
var f = f0;
var lastFID = -1;
var haveFont = false;
for (var i = this.dmesh.pc; --i >= 0; ) if (this.isPolygonDisplayable(i)) {
if (!haveFont || this.dmesh.fontID != lastFID) {
f = this.vwr.shm.getShapePropertyIndex(22, "font", i);
if (f == null) f = f0;
lastFID = f.fid;
this.vwr.gdata.setFont(this.imageFontScaling == 1 ? f : this.vwr.gdata.getFont3DFSS(f.fontFace, f.fontStyle, f.fontSize * this.imageFontScaling));
haveFont = true;
}var s = this.mesh.title[i < this.mesh.title.length ? i : this.mesh.title.length - 1];
var pt = 0;
if (s.length > 1 && s.charAt(0) == '>') {
pt = this.dmesh.pis[i].length - 1;
s = s.substring(1);
if (this.drawType === J.shapespecial.Draw.EnumDrawType.ARC) this.pt1f.setT(this.pt2f);
}if (this.drawType !== J.shapespecial.Draw.EnumDrawType.ARC) this.pt1f.setT(this.vertices[this.dmesh.pis[i][pt]]);
this.tm.transformPtScr(this.pt1f, this.pt1i);
var offset = Math.round(5 * this.imageFontScaling);
if (this.dmesh.titleColor != null) this.vwr.gdata.setColor(this.dmesh.titleColor.intValue());
this.g3d.drawString(s, null, this.pt1i.x + offset, this.pt1i.y - offset, this.pt1i.z, this.pt1i.z, 0);
break;
}
});
});
;//5.0.1-v7 Mon Aug 17 10:07:10 MDT 2026
