UNPKG

biojs-vis-pdbviewer

Version:

A BioJS 2.0 component to view protein structures

514 lines (505 loc) 20.1 kB
Clazz.declarePackage ("J.export"); Clazz.load (["J.export.__CartesianExporter", "java.util.HashSet", "JU.P3"], "J.export._ObjExporter", ["java.lang.Short", "java.util.Hashtable", "JU.AU", "$.BS", "$.CU", "$.Lst", "$.M4", "$.PT", "$.Quat", "$.SB", "$.V3", "J.export.MeshData", "JM.Atom", "JU.C", "$.Escape", "$.Logger", "$.MeshSurface", "JV.Viewer"], function () { c$ = Clazz.decorateAsClass (function () { this.surfacesOnly = false; this.normalizeUV = true; this.mtlout = null; this.objFileRootName = null; this.nMtlBytes = 0; this.textures = null; this.textureFiles = null; this.sphereNum = 1; this.cylinderNum = 1; this.ellipseNum = 1; this.circleNum = 1; this.ellipsoidNum = 1; this.coneNum = 1; this.triangleNum = 1; this.surfaceNum = 1; this.currentVertexOrigin = 1; this.currentNormalOrigin = 1; this.currentTextureOrigin = 1; this.pixelSize = 0; this.ptTemp = null; Clazz.instantialize (this, arguments); }, J["export"], "_ObjExporter", J["export"].__CartesianExporter); Clazz.prepareFields (c$, function () { this.textures = new java.util.HashSet (); this.ptTemp = new JU.P3 (); }); Clazz.makeConstructor (c$, function () { Clazz.superConstructor (this, J["export"]._ObjExporter, []); this.debugPrint ("_WavefrontObjExporter CTOR"); this.commentChar = "# "; }); Clazz.defineMethod (c$, "debugPrint", function (string) { if (false) { JU.Logger.debug (string); }}, "~S"); Clazz.overrideMethod (c$, "outputFace", function (face, map, faceVertexMax) { }, "~A,~A,~N"); Clazz.overrideMethod (c$, "outputCircle", function (pt1, pt2, radius, colix, doFill) { this.debugPrint ("outputCircle"); if (this.surfacesOnly) { this.debugPrint (" Not done owing to surfacesOnly"); return; }if (doFill) { this.outputCircle1 (pt1, pt2, colix, radius); }}, "JU.P3,JU.P3,~N,~N,~B"); Clazz.overrideMethod (c$, "outputCone", function (ptBase, ptTip, radius, colix) { this.debugPrint ("outputCone"); if (this.surfacesOnly) { this.debugPrint (" Not done owing to surfacesOnly"); return; }this.outputCone1 (ptBase, ptTip, radius, colix); }, "JU.P3,JU.P3,~N,~N"); Clazz.overrideMethod (c$, "outputCylinder", function (ptCenter, pt1, pt2, colix, endcaps, radius, ptX, ptY, checkRadius) { if (false) { this.debugPrint ("outputCylinder: colix=" + String.format ("%04x", [Short.$valueOf (colix)])); this.debugPrint (" ptCenter=" + ptCenter); this.debugPrint (" pt1=" + pt1); this.debugPrint (" endcaps=" + endcaps + " NONE=" + 0 + " FLAT=" + 2 + " SPHERICAL=" + 3); this.debugPrint (" radius=" + radius); this.debugPrint (" pt2=" + pt2); this.debugPrint (" ptX=" + ptX); this.debugPrint (" ptY=" + ptY); }if (this.surfacesOnly) { this.debugPrint (" Not done owing to surfacesOnly"); return true; }if (ptX != null) { if (endcaps == 2) { this.outputEllipse1 (ptCenter, pt1, ptX, ptY, colix); this.tempP3.add2 (ptCenter, ptCenter); this.tempP3.sub (ptX); this.outputEllipse1 (ptCenter, pt2, this.tempP3, ptY, colix); }} else if (endcaps == 3) { this.outputSphere (pt1, radius * 1.01, colix, true); this.outputSphere (pt2, radius * 1.01, colix, true); } else if (endcaps == 2) { this.outputCircle1 (pt1, pt2, colix, radius); this.outputCircle1 (pt2, pt1, colix, radius); }this.outputCylinder1 (ptCenter, pt1, pt2, colix, endcaps, radius, ptX, ptY); return true; }, "JU.P3,JU.P3,JU.P3,~N,~N,~N,JU.P3,JU.P3,~B"); Clazz.overrideMethod (c$, "outputEllipsoid", function (center, points, colix) { if (false) { this.debugPrint ("outputEllipsoid: colix=" + String.format ("%04x", [Short.$valueOf (colix)])); this.debugPrint (" center=" + center); this.debugPrint (" points[0]=" + points[0]); this.debugPrint (" points[1]=" + points[1]); this.debugPrint (" points[2]=" + points[2]); }if (this.surfacesOnly) { this.debugPrint (" Not done owing to surfacesOnly"); return; }var a = JU.Quat.getQuaternionFrame (center, points[1], points[3]).toAxisAngle4f (); var sx = points[1].distance (center); var sy = points[3].distance (center); var sz = points[5].distance (center); this.outputEllipsoid1 (center, sx, sy, sz, a, colix); }, "JU.P3,~A,~N"); Clazz.overrideMethod (c$, "outputSphere", function (center, radius, colix, checkRadius) { if (false) { this.debugPrint ("outputSphere: colix=" + String.format ("%04x", [Short.$valueOf (colix)])); this.debugPrint (" center.getClass().getName()=" + center.getClass ().getName ()); this.debugPrint (" center=" + center); this.debugPrint (" center.x=" + center.x); this.debugPrint (" center.y=" + center.y); this.debugPrint (" center.z=" + center.z); this.debugPrint (" radius=" + radius); }if (this.surfacesOnly) { this.debugPrint (" Not done owing to surfacesOnly"); return; }this.outputEllipsoid1 (center, radius, radius, radius, null, colix); }, "JU.P3,~N,~N,~B"); Clazz.overrideMethod (c$, "outputTextPixel", function (pt, argb) { this.debugPrint ("outputTextPixel"); if (this.surfacesOnly) { this.debugPrint (" Not done owing to surfacesOnly"); return; }var colix = JU.C.getColix (argb); this.outputSphere (pt, this.pixelSize, colix, true); }, "JU.P3,~N"); Clazz.overrideMethod (c$, "outputTriangle", function (pt1, pt2, pt3, colix) { this.debugPrint ("outputTriangle"); if (this.surfacesOnly) { this.debugPrint (" Not done owing to surfacesOnly"); return; }this.outputTriangle1 (pt1, pt2, pt3, colix); }, "JU.P3,JU.P3,JU.P3,~N"); Clazz.overrideMethod (c$, "outputHeader", function () { this.debugPrint ("outputHeader"); this.output ("# Created by Jmol " + JV.Viewer.getJmolVersion () + "\n"); }); Clazz.defineMethod (c$, "output", function (pt) { this.debugPrint ("output"); }, "JU.T3"); Clazz.overrideMethod (c$, "drawSurface", function (meshSurface, colix) { if (JU.Logger.debugging) { this.debugPrint ("outputSurface"); this.debugPrint (" nVertices=" + meshSurface.vc); if (meshSurface.normals == null) { this.debugPrint (" no vertex normals"); } else { this.debugPrint (" nNormals=" + meshSurface.vc); }if (meshSurface.pcs == null) { this.debugPrint (" no vertex colors"); } else { this.debugPrint (" nColixes=" + meshSurface.vc); }this.debugPrint (" number of triangles or quads=" + meshSurface.pc); if (meshSurface.pcs == null) { this.debugPrint (" no face colors"); } else { this.debugPrint (" nPolygonColixes=" + meshSurface.pc); }if (meshSurface.bsPolygons == null) { this.debugPrint (" all polygons used"); } else { this.debugPrint (" number of polygons used=" + meshSurface.bsPolygons.cardinality ()); }this.debugPrint (" solid color=" + this.g3d.getColorArgbOrGray (colix)); }var bsPolygons = meshSurface.bsPolygons; var nPolygons = meshSurface.pc; if (meshSurface.normals != null) meshSurface.normalCount = meshSurface.vc; var isAll = (bsPolygons == null); var faces = JU.AU.newInt2 (isAll ? nPolygons : bsPolygons.cardinality ()); var i0 = (isAll ? nPolygons - 1 : bsPolygons.nextSetBit (0)); for (var i = i0, ipt = 0; i >= 0; i = isAll ? i - 1 : bsPolygons.nextSetBit (i + 1)) { var polygon = meshSurface.pis[i]; faces[ipt++] = (meshSurface.haveQuads ? polygon : [polygon[0], polygon[1], polygon[2]]); } var data = JU.MeshSurface.newMesh (false, meshSurface.vs, meshSurface.vc, faces, meshSurface.normals, 0); data.vcs = meshSurface.vcs; var name = "Surface" + this.surfaceNum++; var isSolidColor = (colix != 0); this.addTexture (colix, isSolidColor ? null : name); var dim = null; if (isSolidColor) { this.debugPrint ("outputSurface: coloring solid"); this.debugPrint (" Omitting texture map"); } else { var nFaces = faces.length; var width = Clazz.doubleToInt (Math.ceil (Math.sqrt (nFaces))); var height = Clazz.doubleToInt (nFaces / width); if (nFaces % width != 0) { height++; }dim = [width, height]; this.debugPrint (" width=" + width + " height=" + height + " size = " + (width * height)); var file = this.createTextureFile (name, data, dim); if (file == null || file.getByteCount () == 0) { System.out.println ("Error creating texture file: " + name); this.textureFiles.addLast ("Error creating texture file: " + name); return; }this.textureFiles.addLast (file.getByteCount () + " (" + width + "x" + height + ") " + name); var shortName = file.getName (); this.outputMtl (" map_Kd " + shortName + "\n"); this.outputMtl (" map_Ka " + shortName + "\n"); }var matrix = JU.M4.newM4 (null); matrix.setTranslation (JU.V3.newV (meshSurface.offset)); var bsValid = new JU.BS (); this.addMesh (name, data, matrix, null, colix, dim, bsValid); }, "JU.MeshSurface,~N"); Clazz.overrideMethod (c$, "initializeOutput", function (vwr, privateKey, g3d, params) { this.debugPrint ("initializeOutput: + output"); var retVal = this.initOutput (vwr, privateKey, g3d, params); if (!retVal) { this.debugPrint ("End initializeOutput (error in super):"); return false; }this.pixelSize = 0.5 / this.scalePixelsPerAngstrom; var dot = this.fileName.lastIndexOf ("."); if (dot < 0) { this.debugPrint ("End initializeOutput (Error creating .mtl file):"); return false; }this.objFileRootName = this.fileName.substring (0, dot); try { var mtlFileName = this.objFileRootName + ".mtl"; this.mtlout = vwr.openExportChannel (privateKey, mtlFileName, true); } catch (ex) { if (Clazz.exceptionOf (ex, Exception)) { this.debugPrint ("End initializeOutput (" + ex.getMessage () + "):"); return false; } else { throw ex; } } this.outputMtl ("# Created by Jmol " + JV.Viewer.getJmolVersion () + "\n"); this.output ("\nmtllib " + this.mtlout.getName () + "\n"); this.textureFiles = new JU.Lst (); this.debugPrint ("End initializeOutput:"); return true; }, "JV.Viewer,~N,JU.GData,java.util.Map"); Clazz.overrideMethod (c$, "finalizeOutput", function () { this.debugPrint ("finalizeOutput"); var retVal = this.finalizeOutput2 (); var ret = this.mtlout.closeChannel (); if (ret != null) { JU.Logger.info (ret); ret = "ERROR EXPORTING MTL FILE: " + ret; if (retVal.startsWith ("OK")) return ret; return retVal + " and " + ret; }retVal += ", " + this.nMtlBytes + " " + this.mtlout.getFileName (); for (var string, $string = this.textureFiles.iterator (); $string.hasNext () && ((string = $string.next ()) || true);) { retVal += ", " + string; } this.debugPrint (retVal); this.debugPrint ("End finalizeOutput:"); return retVal; }); Clazz.defineMethod (c$, "outputMtl", function (data) { this.nMtlBytes += data.length; this.mtlout.append (data); }, "~S"); Clazz.defineMethod (c$, "getTextureName", function (colix) { return "k" + JU.Escape.getHexColorFromRGB (this.g3d.getColorArgbOrGray (colix)); }, "~N"); Clazz.defineMethod (c$, "outputCircle1", function (ptCenter, ptPerp, colix, radius) { var data = J["export"].MeshData.getCircleData (); var matrix = new JU.M4 (); this.addTexture (colix, null); var name = "Circle" + this.circleNum++; matrix.setToM3 (this.getRotationMatrix (ptCenter, ptPerp, radius)); matrix.m03 = ptCenter.x; matrix.m13 = ptCenter.y; matrix.m23 = ptCenter.z; matrix.m33 = 1; this.addMesh (name, data, matrix, matrix, colix, null, null); }, "JU.P3,JU.P3,~N,~N"); Clazz.defineMethod (c$, "outputCone1", function (ptBase, ptTip, radius, colix) { var data = J["export"].MeshData.getConeData (); var matrix = new JU.M4 (); this.addTexture (colix, null); var name = "Cone" + this.coneNum++; matrix.setToM3 (this.getRotationMatrix (ptBase, ptTip, radius)); matrix.m03 = ptBase.x; matrix.m13 = ptBase.y; matrix.m23 = ptBase.z; matrix.m33 = 1; this.addMesh (name, data, matrix, matrix, colix, null, null); }, "JU.P3,JU.P3,~N,~N"); Clazz.defineMethod (c$, "outputEllipse1", function (ptCenter, ptZ, ptX, ptY, colix) { var data = J["export"].MeshData.getCircleData (); var matrix = new JU.M4 (); this.addTexture (colix, null); var name = "Ellipse" + this.ellipseNum++; matrix.setToM3 (this.getRotationMatrix (ptCenter, ptZ, 1, ptX, ptY)); matrix.m03 = ptZ.x; matrix.m13 = ptZ.y; matrix.m23 = ptZ.z; matrix.m33 = 1; this.addMesh (name, data, matrix, matrix, colix, null, null); return true; }, "JU.P3,JU.P3,JU.P3,JU.P3,~N"); Clazz.defineMethod (c$, "outputEllipsoid1", function (center, rx, ry, rz, a, colix) { var data = JU.MeshSurface.getSphereData (3); this.addTexture (colix, null); var name; if (Clazz.instanceOf (center, JM.Atom)) { var atom = center; name = JU.PT.replaceAllCharacters (atom.getAtomName (), " \t", "") + "_Atom"; } else if (rx == ry && rx == rz) { name = "Sphere" + this.sphereNum++; } else { name = "Ellipsoid" + this.ellipsoidNum++; }this.setSphereMatrix (center, rx, ry, rz, a, this.sphereMatrix); this.addMesh (name, data, this.sphereMatrix, this.sphereMatrix, colix, null, null); }, "JU.P3,~N,~N,~N,JU.A4,~N"); Clazz.defineMethod (c$, "outputCylinder1", function (ptCenter, pt1, pt2, colix, endcaps, radius, ptX, ptY) { var data = J["export"].MeshData.getCylinderData (false); var matrix = new JU.M4 (); this.addTexture (colix, null); var name = "Cylinder" + this.cylinderNum++; var n = (ptX != null && endcaps == 0 ? 2 : 1); for (var i = 0; i < n; i++) { if (ptX == null) matrix.setToM3 (this.getRotationMatrix (pt1, pt2, radius)); else matrix.setToM3 (this.getRotationMatrix (ptCenter, pt2, radius, ptX, ptY)); matrix.m03 = pt1.x; matrix.m13 = pt1.y; matrix.m23 = pt1.z; matrix.m33 = 1; } this.addMesh (name, data, matrix, matrix, colix, null, null); }, "JU.P3,JU.P3,JU.P3,~N,~N,~N,JU.P3,JU.P3"); Clazz.defineMethod (c$, "outputTriangle1", function (pt1, pt2, pt3, colix) { var data = J["export"].MeshData.getTriangleData (pt1, pt2, pt3); this.addTexture (colix, null); var name = "Triangle" + this.triangleNum++; var matrix = JU.M4.newM4 (null); this.addMesh (name, data, matrix, matrix, colix, null, null); }, "JU.P3,JU.P3,JU.P3,~N"); Clazz.defineMethod (c$, "addTexture", function (colix, name) { var scolix = Short.$valueOf (colix); if (name == null && this.textures.contains (scolix)) { return; }this.textures.add (scolix); var sb = new JU.SB (); sb.append ("\nnewmtl " + (name == null ? this.getTextureName (colix) : name) + "\n"); sb.append (" Ns 163\n"); sb.append (" Tr " + J["export"].___Exporter.opacityFractionalFromColix (colix) + "\n"); sb.append (" Ni 0.001\n"); sb.append (" illum 2\n"); sb.append (" Ka 0.20 0.20 0.20\n"); sb.append (" Kd " + this.rgbFractionalFromColix (colix) + "\n"); sb.append (" Ks 0.25 0.25 0.25\n"); this.outputMtl (sb.toString ()); }, "~N,~S"); Clazz.defineMethod (c$, "addMesh", function (name, data, matrix, matrix1, colix, dim, bsValid) { if (this.surfacesOnly) { if (name == null || !name.startsWith ("Surface")) { return; }}this.output ("\ng " + name + "\n"); this.output ("usemtl " + (dim == null ? this.getTextureName (colix) : name) + "\n"); var faces = data.getFaces (); var nFaces = faces.length; if (bsValid != null) for (var face, $face = 0, $$face = faces; $face < $$face.length && ((face = $$face[$face]) || true); $face++) for (var i, $i = 0, $$i = face; $i < $$i.length && ((i = $$i[$i]) || true); $i++) bsValid.set (i); var vertices = data.getVertices (); var nVertices = data.vc; var map = Clazz.newIntArray (nVertices, 0); var nCoord = this.getCoordinateMap (vertices, map, bsValid); this.output ("# Number of vertices: " + nCoord + "\n"); this.outputList (vertices, nVertices, matrix, "v ", bsValid); nVertices = nCoord; var normals = data.normals; var nNormals = data.normalCount; var map2 = null; var vNormals = null; if (normals != null) { vNormals = new JU.Lst (); map2 = this.getNormalMap (normals, nNormals, bsValid, vNormals); nNormals = vNormals.size (); this.output ("# Number of normals: " + nNormals + "\n"); for (var i = 0; i < nNormals; i++) this.output ("vn " + vNormals.get (i)); }if (dim != null) { this.output ("# Number of texture coordinates: " + nFaces + "\n"); var width = dim[0]; var height = dim[1]; var u; var v; for (var row = 0, iFace = 0; row < height; row++) { v = row + .5; if (this.normalizeUV) v /= height; for (var col = 0; col < width; col++) { u = col + .5; if (this.normalizeUV) u /= width; this.output ("vt " + u + " " + v + "\n"); if (++iFace == nFaces) break; } } if (!this.normalizeUV) { this.output ("vt 0.0 0.0\n"); this.output ("vt " + width + " " + height + "\n"); }}this.output ("# Number of faces: " + nFaces + "\n"); for (var i = 0; i < nFaces; i++) if (dim != null) this.outputFace2 (faces[i], i, map, map2); else this.outputFace1 (faces[i], map, map2); if (dim != null) this.currentTextureOrigin += nFaces; this.currentVertexOrigin += nVertices; this.currentNormalOrigin += nNormals; }, "~S,JU.MeshSurface,JU.M4,JU.M4,~N,~A,JU.BS"); Clazz.defineMethod (c$, "outputList", function (pts, nPts, m, prefix, bsValid) { for (var i = 0; i < nPts; i++) { if (bsValid != null && !bsValid.get (i)) continue; this.ptTemp.setT (pts[i]); if (m != null) m.rotTrans (this.ptTemp); this.output (prefix + this.ptTemp.x + " " + this.ptTemp.y + " " + this.ptTemp.z + "\n"); } }, "~A,~N,JU.M4,~S,JU.BS"); Clazz.defineMethod (c$, "outputFace1", function (face, map, map2) { this.output ("f"); for (var i, $i = 0, $$i = face; $i < $$i.length && ((i = $$i[$i]) || true); $i++) this.output (" " + ((map == null ? i : map[i]) + this.currentVertexOrigin) + "//" + ((map2 == null ? i : map2[i]) + this.currentNormalOrigin)); this.output ("\n"); }, "~A,~A,~A"); Clazz.defineMethod (c$, "outputFace2", function (face, vt, map, map2) { this.output ("f"); for (var i, $i = 0, $$i = face; $i < $$i.length && ((i = $$i[$i]) || true); $i++) { this.output (" " + ((map == null ? i : map[i]) + this.currentVertexOrigin) + "/" + (this.currentTextureOrigin + vt) + "/" + ((map2 == null ? i : map2[i]) + this.currentNormalOrigin)); } this.output ("\n"); }, "~A,~N,~A,~A"); Clazz.defineMethod (c$, "createTextureFile", function (name, data, dim) { this.debugPrint ("createTextureFile: " + name); var colixes = (data.pcs == null ? data.vcs : data.pcs); if (colixes == null || colixes.length == 0) { this.debugPrint ("createTextureFile: Array problem"); this.debugPrint (" colixes=" + colixes + " data=" + data); if (colixes != null) { this.debugPrint (" colixes.length=" + colixes.length); }return null; }var nUsed = data.pis.length; if (nUsed <= 0) { this.debugPrint ("createTextureFile: nFaces = 0"); return null; }var width = dim[0]; var height = dim[1]; var textureType = "png"; var row = height - 1; var col = 0; var sum = new JU.P3 (); var w = width * 3; var h = height * 3; var bytes = (textureType.equals ("tga") ? Clazz.newByteArray (h, w * 3, 0) : null); var rgbbuf = (bytes == null ? Clazz.newIntArray (h * w, 0) : null); var ptTemp = new JU.P3 (); for (var i = 0; i < data.pis.length; i++) { var rgb; if (data.pcs == null) { var face = data.pis[i]; sum.set (0, 0, 0); for (var iVertex, $iVertex = 0, $$iVertex = face; $iVertex < $$iVertex.length && ((iVertex = $$iVertex[$iVertex]) || true); $iVertex++) sum.add (JU.CU.colorPtFromInt (this.g3d.getColorArgbOrGray (colixes[iVertex]), ptTemp)); sum.scale (1.0 / face.length); rgb = JU.CU.colorPtToFFRGB (sum); } else { rgb = this.g3d.getColorArgbOrGray (colixes[i]); }if (bytes == null) { for (var j = 0; j < 3; j++) for (var k = 0; k < 3; k++) rgbbuf[(row * 3 + k) * w + col * 3 + j] = rgb; } else { }if ((col = (col + 1) % width) == 0) row--; } try { var params = new java.util.Hashtable (); var fname = this.fileName; if (rgbbuf != null) { params.put ("rgbbuf", rgbbuf); params.put ("fileName", this.objFileRootName + "_" + name + "." + textureType); params.put ("type", textureType); params.put ("width", Integer.$valueOf (w)); params.put ("height", Integer.$valueOf (h)); fname = this.fileName = this.vwr.outputToFile (params); }this.debugPrint ("End createTextureFile: " + fname); return params.get ("outputChannel"); } catch (ex) { if (Clazz.exceptionOf (ex, Exception)) { this.debugPrint ("End createTextureFile (" + ex.getMessage () + "):"); return null; } else { throw ex; } } }, "~S,JU.MeshSurface,~A"); Clazz.defineStatics (c$, "debug", false); });