label.ts 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Loci } from '../../../mol-model/loci';
  7. import { RuntimeContext } from '../../../mol-task';
  8. import { stringToWords } from '../../../mol-util/string';
  9. import { Text } from '../../../mol-geo/geometry/text/text';
  10. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  11. import { ColorNames } from '../../../mol-util/color/names';
  12. import { ShapeRepresentation } from '../representation';
  13. import { Representation, RepresentationParamsGetter, RepresentationContext } from '../../representation';
  14. import { Shape } from '../../../mol-model/shape';
  15. import { TextBuilder } from '../../../mol-geo/geometry/text/text-builder';
  16. import { Sphere3D } from '../../../mol-math/geometry';
  17. import { lociLabel } from '../../../mol-theme/label';
  18. export interface LabelData {
  19. infos: { loci: Loci, label?: string }[]
  20. }
  21. const TextParams = {
  22. ...Text.Params,
  23. borderWidth: PD.Numeric(0.2, { min: 0, max: 0.5, step: 0.01 }),
  24. textColor: PD.Color(ColorNames.black),
  25. textSize: PD.Numeric(0.8, { min: 0.1, max: 5, step: 0.1 }),
  26. offsetZ: PD.Numeric(2, { min: 0, max: 10, step: 0.1 }),
  27. }
  28. type TextParams = typeof TextParams
  29. const LabelVisuals = {
  30. 'text': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<LabelData, TextParams>) => ShapeRepresentation(getTextShape, Text.Utils),
  31. }
  32. type LabelVisualName = keyof typeof LabelVisuals
  33. const LabelVisualOptions = Object.keys(LabelVisuals).map(name => [name, stringToWords(name)] as [LabelVisualName, string])
  34. export const LabelParams = {
  35. ...TextParams,
  36. visuals: PD.MultiSelect<LabelVisualName>(['text'], LabelVisualOptions),
  37. }
  38. export type LabelParams = typeof LabelParams
  39. export type LabelProps = PD.Values<LabelParams>
  40. //
  41. const tmpSphere = Sphere3D()
  42. function buildText(data: LabelData, props: LabelProps, text?: Text): Text {
  43. const builder = TextBuilder.create(props, 128, 64, text)
  44. for (let i = 0, il = data.infos.length; i < il; ++i) {
  45. const d = data.infos[i]
  46. const sphere = Loci.getBoundingSphere(d.loci, tmpSphere)
  47. if (!sphere) continue
  48. const { center, radius } = sphere
  49. const label = d.label || lociLabel(d.loci, { hidePrefix: true, htmlStyling: false })
  50. builder.add(label, center[0], center[1], center[2], radius, 1, i)
  51. }
  52. return builder.getText()
  53. }
  54. function getTextShape(ctx: RuntimeContext, data: LabelData, props: LabelProps, shape?: Shape<Text>) {
  55. const text = buildText(data, props, shape && shape.geometry);
  56. const getLabel = function (groupId: number) {
  57. return 'Label Text'
  58. }
  59. return Shape.create('Label Text', data, text, () => props.textColor, () => props.textSize, getLabel)
  60. }
  61. //
  62. export type LabelRepresentation = Representation<LabelData, LabelParams>
  63. export function LabelRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<LabelData, LabelParams>): LabelRepresentation {
  64. return Representation.createMulti('Label', ctx, getParams, Representation.StateBuilder, LabelVisuals as unknown as Representation.Def<LabelData, LabelParams>)
  65. }