Issue #826. Mesh surfaces

Implement wireframe style for meshes.
Also a number of changes to work with newer versions of devtools.
This commit is contained in:
David Koes
2025-04-03 11:54:27 -04:00
parent 6c1f0d44bf
commit a5002903a8
30 changed files with 876 additions and 956 deletions

View File

@@ -1,38 +0,0 @@
{
"parser": "@babel/eslint-parser",
"parserOptions": {
"requireConfigFile": false
},
"extends": ["eslint:recommended"],
"ignorePatterns": ["**/vendor/*.js"],
"rules": {
"no-prototype-builtins": "off"
},
"env": {
"es6": true
},
"globals": {
"$3Dmol": "writable",
"console": "writable",
"document": "readonly",
"$": "readonly",
"window": "readonly",
"self": "writable" ,
"module": "readonly",
"Blob": "readonly",
"pako": "readonly",
"UPNG": "readonly",
"netcdfjs": "readonly",
"XMLHttpRequest": "readonly",
"alert": "readonly",
"setTimeout": "readonly",
"clearTimeout": "readonly",
"setInterval": "readonly",
"clearInterval": "readonly",
"Worker": "readonly",
"MMTF": "readonly",
"TextDecoder": "readonly",
"FileReader": "readonly",
"ProteinSurface": "readonly"
}
}

60
eslint.config.cjs Normal file
View File

@@ -0,0 +1,60 @@
const {
defineConfig,
globalIgnores,
} = require("eslint/config");
const babelParser = require("@babel/eslint-parser");
const js = require("@eslint/js");
const {
FlatCompat,
} = require("@eslint/eslintrc");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
module.exports = defineConfig([globalIgnores(["**/vendor/*.js"]), {
extends: compat.extends("eslint:recommended"),
languageOptions: {
globals: {
$3Dmol: "writable",
console: "writable",
document: "readonly",
$: "readonly",
window: "readonly",
self: "writable",
module: "readonly",
Blob: "readonly",
pako: "readonly",
UPNG: "readonly",
netcdfjs: "readonly",
XMLHttpRequest: "readonly",
alert: "readonly",
setTimeout: "readonly",
clearTimeout: "readonly",
setInterval: "readonly",
clearInterval: "readonly",
Worker: "readonly",
MMTF: "readonly",
TextDecoder: "readonly",
FileReader: "readonly",
ProteinSurface: "readonly",
},
parser: babelParser,
ecmaVersion: 5,
sourceType: "script",
parserOptions: {
requireConfigFile: false,
},
},
rules: {
"no-prototype-builtins": "off",
},
}]);

1556
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,8 @@
"coverageReporters": [
"lcov",
"text"
]
],
"testEnvironment": "jest-fixed-jsdom"
},
"engines": {
"npm": ">=8.11",
@@ -46,7 +47,7 @@
"doc": "rm -rf doc/ && npx jsdoc -c jsdoc.conf.json src doc.md"
},
"dependencies": {
"iobuffer": "^5.3.1",
"iobuffer": "^5.0.0",
"netcdfjs": "^3.0.0",
"pako": "^2.1.0",
"upng-js": "^2.1.0"
@@ -61,11 +62,12 @@
"clean-jsdoc-theme": "github:3dmol/clean-jsdoc-theme#master",
"codecov": "^3.8.3",
"del": "^7.0.0",
"eslint": "^8.30.0",
"eslint-webpack-plugin": "^3.2.0",
"eslint": "^9.0.0",
"eslint-webpack-plugin": "^5.0.0",
"glcheck": "github:3dmol/glcheck",
"jest": "^29.3.1",
"jest": "^29.0.0",
"jest-environment-jsdom": "^29.3.1",
"jest-fixed-jsdom": "^0.0.9",
"jest-webgl-canvas-mock": "^0.2.3",
"jquery": "^3.6.3",
"jsdoc": "^4.0.0",

View File

@@ -27,6 +27,13 @@ interface SurfObj {
style?: SurfaceStyleSpec;
}
interface Surface extends Array<SurfObj> {
style?: SurfaceStyleSpec;
atomsel?: AtomSelectionSpec;
allsel?: AtomSelectionSpec;
focus?: AtomSelectionSpec;
}
/**
* WebGL-based 3Dmol.js viewer
* Note: The preferred method of instantiating a GLViewer is through {@link createViewer}
@@ -48,7 +55,7 @@ export class GLViewer {
private glDOM: HTMLCanvasElement | null = null;
private models: GLModel[] = []; // atomistic molecular models
private surfaces: Record<number,SurfObj[]> = {};
private surfaces: Record<number,Surface> = {};
private shapes = []; // Generic shapes
private labels: Label[] = [];
private clickables = []; //things you can click on
@@ -1840,8 +1847,9 @@ export class GLViewer {
geo.buffersNeedUpdate = true;
surfArr[n].mat.needsUpdate = true;
if (surfArr[n].done)
if (surfArr[n].done) {
surfArr[n].finished = true;
}
// remove partially rendered surface
if (surfArr[n].lastGL)
@@ -1855,6 +1863,9 @@ export class GLViewer {
smesh = new Line(geo, surfArr[n].mat);
}
else {
if('wireframe' in surfArr.style && surfArr.style.wireframe) {
geo.setUpWireframe();
}
smesh = new Mesh(geo, surfArr[n].mat);
}
if (surfArr[n].mat.transparent && surfArr[n].mat.opacity == 0) {
@@ -4298,6 +4309,10 @@ export class GLViewer {
mat.transparent = true;
}
if (style.wireframe !== undefined) {
mat.wireframe = style.wireframe;
}
return mat;
}
@@ -4310,7 +4325,7 @@ export class GLViewer {
* @returns {number} surfid
*/
public addMesh(mesh: Mesh) {
var surfobj = {
let surfobj: SurfObj = {
geo: mesh.geometry,
mat: mesh.material,
done: true,
@@ -4399,7 +4414,7 @@ export class GLViewer {
}
}
var addSurfaceHelper = function addSurfaceHelper(surfobj, atomlist: AtomSpec[], atomsToShow: AtomSpec[]) {
var addSurfaceHelper = function addSurfaceHelper(surfobj: SurfObj, atomlist: AtomSpec[], atomsToShow: AtomSpec[]) {
//function returns promise with surfid resolved
if (!focus) {
focusSele = atomsToShow;
@@ -4581,12 +4596,12 @@ export class GLViewer {
style = style || {};
mat = GLViewer.getMatWithStyle(style);
var surfobj: any = [];
let surf: Surface = [];
//save configuration of surface
surfobj.style = style;
surfobj.atomsel = atomsel;
surfobj.allsel = allsel;
surfobj.focus = focus;
surf.style = style;
surf.atomsel = atomsel;
surf.allsel = allsel;
surf.focus = focus;
var promise = null;
if (symmetries) { //do preprocessing
var modelsAtomList = {};
@@ -4604,7 +4619,7 @@ export class GLViewer {
var promises = [];
for (n = 0; n < this.models.length; n++) {
if (modelsAtomsToShow[n].length > 0) {
surfobj.push({
surf.push({
geo: new Geometry(true),
mat: mat,
done: false,
@@ -4612,22 +4627,22 @@ export class GLViewer {
symmetries: this.models[n].getSymmetries()
// also webgl initialized
});
promises.push(addSurfaceHelper(surfobj[surfobj.length - 1], modelsAtomList[n], modelsAtomsToShow[n]));
promises.push(addSurfaceHelper(surf[surf.length - 1], modelsAtomList[n], modelsAtomsToShow[n]));
}
}
promise = Promise.all(promises);
}
else {
surfobj.push({
surf.push({
geo: new Geometry(true),
mat: mat,
done: false,
finished: false,
symmetries: [new Matrix4()]
});
promise = addSurfaceHelper(surfobj[surfobj.length - 1], atomlist, atomsToShow);
promise = addSurfaceHelper(surf[surf.length - 1], atomlist, atomsToShow);
}
this.surfaces[surfid] = surfobj;
this.surfaces[surfid] = surf;
promise.surfid = surfid;
if (surfacecallback && typeof (surfacecallback) == "function") {
@@ -4663,6 +4678,9 @@ export class GLViewer {
for (let i = 0; i < surfArr.length; i++) {
var mat = surfArr[i].mat = GLViewer.getMatWithStyle(style);
surfArr[i].mat.side = FrontSide;
if (style.wireframe) {
surfArr[i].geo.setUpWireframe();
}
if (style.color) {
surfArr[i].mat.color = CC.color(style.color);
surfArr[i].geo.colorsNeedUpdate = true;
@@ -5204,6 +5222,8 @@ export interface SurfaceStyleSpec {
volscheme?: Gradient;
/** format of voldata if not a {VolumeData} object */
volformat?: string;
/** Display as wireframe */
wireframe?: boolean;
/* specifies a numeric atom property (prop) and color mapping (scheme) such as {@link $3Dmol.Gradient.RWB}. Deprecated, use colorscheme instead. */
map?: Record<string, unknown>
};

View File

@@ -466,7 +466,7 @@ export class Geometry extends EventDispatcher {
}
setColor(...setcolor: Parameters<GeometryGroup["setColor"]>): void {
var len = this.geometryGroups.length;
let len = this.geometryGroups.length;
for (var g = 0; g < len; g++) {
var geoGroup = this.geometryGroups[g];
geoGroup.setColor(...setcolor);
@@ -474,7 +474,8 @@ export class Geometry extends EventDispatcher {
}
setUpWireframe(...lineIndexArgs: Parameters<GeometryGroup["setLineIndices"]>) {
for (var g = 0; g < this.groups; g++) {
let len = this.geometryGroups.length;
for (var g = 0; g < len; g++) {
var geoGroup = this.geometryGroups[g];
geoGroup.setLineIndices(...lineIndexArgs);

View File

@@ -83,7 +83,7 @@ function view<T>(data: Uint8Array, byteSize: number, c: new (buffer: ArrayBuffer
if (data.byteOffset != 0 || data.byteLength != data.buffer.byteLength) { //dkoes - extract from larger buffer if needed
data = new Uint8Array(data);
}
if (IsNativeEndianLittle) return new c(data.buffer);
if (IsNativeEndianLittle) return new c(data.buffer as ArrayBuffer);
return new c(flipByteOrder(data, byteSize));
}

View File

@@ -614,13 +614,11 @@ $3Dmol.UI = (function () {
}
else {
if (allControl.value) {
let id = sid;
stateManager.addSelection({}, id);
finalizeSelection(id);
stateManager.addSelection({}, sid);
finalizeSelection(sid);
}
else {
let id = sid;
checkAndAddSelection(id);
checkAndAddSelection(sid);
}
}
});

View File

@@ -47,12 +47,8 @@ export function isNumeric(obj) {
!isNaN(obj - parseFloat(obj));
};
export function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
export function isEmptyObject(obj: object) {
return Object.keys(obj).length === 0;
};
export type Func = Function|string|undefined|null;

View File

@@ -0,0 +1,8 @@
$3Dmol.download("pdb:4DLN",viewer,{},function(){
viewer.zoomTo({chain:'A'});
viewer.rotate(-110);
viewer.addSurface("VDW", {wireframe:true},{chain:'A'});
viewer.render();
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 KiB

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function () { };

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function () { };

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function () { };

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function () { };

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function () { };

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,4 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};
let $3Dmol = require("../../build/3Dmol.js");

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -1,6 +1,3 @@
/**
*@jest-environment jsdom
*/
global.$ = require("jquery");
global.URL.createObjectURL = function() {};

View File

@@ -46,7 +46,7 @@ module.exports = {
$: "jquery"
}),
new webpack.BannerPlugin({ banner }),
new ESLintPlugin()
new ESLintPlugin({exclude: ['node_modules']})
],
stats: {
errorDetails: true,