Skip to content
Snippets Groups Projects
Commit 6c78adb3 authored by JonStargaryen's avatar JonStargaryen
Browse files

adds visuals

parent f6262f4b
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,7 @@
*/
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { Vec3 } from '../../mol-math/linear-algebra';
import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
import { Representation, RepresentationContext, RepresentationParamsGetter } from '../../mol-repr/representation';
import { Structure } from '../../mol-model/structure';
import { Spheres } from '../../mol-geo/geometry/spheres/spheres';
......@@ -19,13 +19,55 @@ import { ShapeRepresentation } from '../../mol-repr/shape/representation';
import { Shape } from '../../mol-model/shape';
import { ColorNames } from '../../mol-util/color/names';
import { RuntimeContext } from '../../mol-task';
import { Lines } from '../../mol-geo/geometry/lines/lines';
import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
import { LinesBuilder } from '../../mol-geo/geometry/lines/lines-builder';
import { Circle } from '../../mol-geo/primitive/circle';
import { transformPrimitive } from '../../mol-geo/primitive/primitive';
import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder';
const MembraneOrientationParams = {
const SharedParams = {
color: PD.Color(ColorNames.lightgrey)
};
const BilayerSpheresParams = {
...SharedParams,
...Spheres.Params,
color: PD.Color(ColorNames.lightgrey),
size: PD.Numeric(1, { min: 0.1, max: 10, step: 0.1 }, { description: 'Size of spheres that represent membrane planes' }),
density: PD.Numeric(1, { min: 0.25, max: 10, step: 0.25 }, { description: 'Distance between spheres'})
};
export type BilayerSpheresParams = typeof BilayerSpheresParams
export type BilayerSpheresProps = PD.Values<BilayerSpheresParams>
const BilayerPlanesParams = {
...SharedParams,
...Mesh.Params
};
export type BilayerPlanesParams = typeof BilayerPlanesParams
export type BilayerPlanesProps = PD.Values<BilayerPlanesParams>
const BilayerRimsParams = {
...SharedParams,
...Lines.Params,
lineSizeAttenuation: PD.Boolean(true),
linesSize: PD.Numeric(0.04, { min: 0.01, max: 5, step: 0.01 }),
dashLength: PD.Numeric(0.04, { min: 0.01, max: 0.2, step: 0.01 })
};
export type BilayerRimsParams = typeof BilayerRimsParams
export type BilayerRimsProps = PD.Values<BilayerRimsParams>
const MembraneOrientationVisuals = {
'bilayer-spheres': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<MembraneOrientation, BilayerSpheresParams>) => ShapeRepresentation(getBilayerSpheres, Spheres.Utils, { modifyState: s => ({ ...s, pickable: false }) }),
'bilayer-planes': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<MembraneOrientation, BilayerPlanesParams>) => ShapeRepresentation(getBilayerPlanes, Mesh.Utils, { modifyState: s => ({ ...s, pickable: false }) }),
'bilayer-rims': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<MembraneOrientation, BilayerRimsParams>) => ShapeRepresentation(getBilayerRims, Lines.Utils, { modifyState: s => ({ ...s, pickable: false }) })
};
export const MembraneOrientationParams = {
...BilayerSpheresParams,
...BilayerPlanesParams,
...BilayerRimsParams,
visuals: PD.MultiSelect(['bilayer-spheres', 'bilayer-planes', 'bilayer-rims'], PD.objectToOptions(MembraneOrientationVisuals)),
};
export type MembraneOrientationParams = typeof MembraneOrientationParams
export type MembraneOrientationProps = PD.Values<MembraneOrientationParams>
......@@ -38,11 +80,6 @@ export function MembraneOrientationRepresentation(ctx: RepresentationContext, ge
return Representation.createMulti('Membrane Orientation', ctx, getParams, StructureRepresentationStateBuilder, MembraneOrientationVisuals as unknown as Representation.Def<Structure, MembraneOrientationParams>);
}
const MembraneOrientationVisuals = {
'membrane-orientation': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<MembraneOrientation, MembraneOrientationParams>) => ShapeRepresentation(getMembraneSpheres, Spheres.Utils),
};
export const MembraneOrientationRepresentationProvider = StructureRepresentationProvider({
name: 'membrane-orientation',
label: 'Membrane Orientation',
......@@ -55,24 +92,74 @@ export const MembraneOrientationRepresentationProvider = StructureRepresentation
isApplicable: (structure: Structure) => structure.elementCount > 0
});
function getMembraneSpheres(ctx: RuntimeContext, data: Structure, props: MembraneOrientationProps) {
function getBilayerRims(ctx: RuntimeContext, data: Structure, props: BilayerRimsProps): Shape<Lines> {
const { p1, p2, centroid, normal, radius } = MembraneOrientationProvider.get(data).value!;
const builder = LinesBuilder.create(128, 64);
getLayerCircle(builder, p1, centroid, normal, radius);
getLayerCircle(builder, p2, centroid, normal, radius);
return Shape.create(name, data, builder.getLines(), () => props.color, () => /*props.linesSize*/1, () => '');
}
function getLayerCircle(builder: LinesBuilder, p: Vec3, centroid: Vec3, normal: Vec3, radius: number) {
const circle = getCircle(p, centroid, normal, radius);
const { indices, vertices } = circle;
for (let j = 0, jl = indices.length; j < jl; j += 3) {
if (j % 2 === 1) continue; // draw every other segment to get dashes
const start = indices[j] * 3;
const end = indices[j + 1] * 3;
const startX = vertices[start];
const startY = vertices[start + 1];
const startZ = vertices[start + 2];
const endX = vertices[end];
const endY = vertices[end + 1];
const endZ = vertices[end + 2];
builder.add(startX, startY, startZ, endX, endY, endZ, 0);
}
}
const tmpMat = Mat4();
function getCircle(p: Vec3, centroid: Vec3, normal: Vec3, radius: number) {
Mat4.targetTo(tmpMat, p, centroid, normal);
Mat4.setTranslation(tmpMat, p);
Mat4.mul(tmpMat, tmpMat, Mat4.rotX90);
const circle = Circle({ radius });
return transformPrimitive(circle, tmpMat);
}
function getBilayerPlanes(ctx: RuntimeContext, data: Structure, props: BilayerPlanesProps): Shape<Mesh> {
const { p1, p2, centroid, normal, radius } = MembraneOrientationProvider.get(data).value!;
const state = MeshBuilder.createState(128, 64);
getLayerPlane(state, p1, centroid, normal, radius);
getLayerPlane(state, p2, centroid, normal, radius);
return Shape.create(name, data, MeshBuilder.getMesh(state), () => props.color, () => /*props.size*/1, () => '');
}
function getLayerPlane(state: MeshBuilder.State, p: Vec3, centroid: Vec3, normal: Vec3, radius: number) {
const circle = getCircle(p, centroid, normal, radius);
state.currentGroup = 0;
MeshBuilder.addPrimitive(state, Mat4.id, circle);
MeshBuilder.addPrimitiveFlipped(state, Mat4.id, circle);
}
function getBilayerSpheres(ctx: RuntimeContext, data: Structure, props: BilayerSpheresProps): Shape<Spheres> {
const { density } = props;
const { radius, p1, p2, normal } = MembraneOrientationProvider.get(data).value!;;
const { radius, p1, p2, normal } = MembraneOrientationProvider.get(data).value!;
const spheresBuilder = SpheresBuilder.create();
createMembraneLayer(spheresBuilder, p1, normal, density, radius);
createMembraneLayer(spheresBuilder, p2, normal, density, radius);
return Shape.create(name, data, spheresBuilder.getSpheres(), () => props.color, () => props.size, () => 'Membrane Boundaries');
getLayerSpheres(spheresBuilder, p1, normal, density, radius * radius);
getLayerSpheres(spheresBuilder, p2, normal, density, radius * radius);
return Shape.create(name, data, spheresBuilder.getSpheres(), () => props.color, () => props.size, () => '');
}
function createMembraneLayer(spheresBuilder: SpheresBuilder, point: Vec3, normalVector: Vec3, density: number, radius: number) {
function getLayerSpheres(spheresBuilder: SpheresBuilder, point: Vec3, normalVector: Vec3, density: number, sqRadius: number) {
Vec3.normalize(normalVector, normalVector);
const d = -Vec3.dot(normalVector, point);
const rep = Vec3();
for (let i = -1000, il = 1000; i < il; i += density) {
for (let j = -1000, jl = 1000; j < jl; j += density) {
Vec3.set(rep, i, j, normalVector[2] === 0 ? 0 : -(d + i * normalVector[0] + j * normalVector[1]) / normalVector[2]);
if (Vec3.squaredDistance(rep, point) < radius) {
if (Vec3.squaredDistance(rep, point) < sqRadius) {
spheresBuilder.add(rep[0], rep[1], rep[2], 0);
}
}
......
......@@ -123,7 +123,7 @@ export async function calculate(runtime: RuntimeContext, structure: Structure, p
const membrane = initialMembrane.qmax! > alternativeMembrane.qmax! ? initialMembrane : alternativeMembrane;
return MembraneOrientation(membrane.planePoint1, membrane.planePoint2, membrane.normalVector!, ctx.extent * ctx.extent);
return MembraneOrientation(membrane.planePoint1, membrane.planePoint2, membrane.normalVector!, ctx.extent, ctx.centroid);
}
interface MembraneCandidate {
......
......@@ -14,11 +14,12 @@ interface MembraneOrientation {
// normal vector of membrane layer
readonly normal: Vec3,
// the radius of the membrane layer
readonly radius: number
readonly radius: number,
readonly centroid: Vec3
}
function MembraneOrientation(p1: Vec3, p2: Vec3, normal: Vec3, radius: number): MembraneOrientation {
return { p1, p2, normal, radius };
function MembraneOrientation(p1: Vec3, p2: Vec3, normal: Vec3, radius: number, centroid: Vec3): MembraneOrientation {
return { p1, p2, normal, radius, centroid };
}
export { MembraneOrientation };
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment