structure-distance.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /**
  2. * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { Structure, Unit } from '../../structure'
  7. import { Vec3 } from '../../../../mol-math/linear-algebra';
  8. import { QueryFn, QueryContext } from '../context';
  9. export function checkStructureMinMaxDistance(ctx: QueryContext, a: Structure, b: Structure, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
  10. if (a.elementCount === 0 || b.elementCount === 0) return true;
  11. if (a.elementCount <= b.elementCount) return MinMaxDist.check(ctx, a, b, minDist, maxDist, elementRadius);
  12. return MinMaxDist.check(ctx, b, a, minDist, maxDist, elementRadius);
  13. }
  14. export function checkStructureMaxRadiusDistance(ctx: QueryContext, a: Structure, b: Structure, maxDist: number, elementRadius: QueryFn<number>) {
  15. if (a.elementCount === 0 || b.elementCount === 0) return true;
  16. if (a.elementCount <= b.elementCount) return MaxRadiusDist.check(ctx, a, b, maxDist, elementRadius);
  17. return MaxRadiusDist.check(ctx, b, a, maxDist, elementRadius);
  18. }
  19. namespace MinMaxDist {
  20. const enum Result {
  21. BelowMin,
  22. WithinMax,
  23. Miss
  24. }
  25. const distVec = Vec3.zero();
  26. function inUnit(ctx: QueryContext, unit: Unit, p: Vec3, eRadius: number, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
  27. const { elements, conformation: { position } } = unit, dV = distVec;
  28. ctx.element.unit = unit;
  29. let withinRange = false;
  30. for (let i = 0, _i = elements.length; i < _i; i++) {
  31. const e = elements[i];
  32. ctx.element.element = e;
  33. const d = Math.max(0, Vec3.distance(p, position(e, dV)) - eRadius - elementRadius(ctx));
  34. if (d < minDist) return Result.BelowMin;
  35. if (d < maxDist) withinRange = true;
  36. }
  37. return withinRange ? Result.WithinMax : Result.Miss;
  38. }
  39. export function toPoint(ctx: QueryContext, s: Structure, point: Vec3, radius: number, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
  40. const { units } = s;
  41. let withinRange = false;
  42. for (let i = 0, _i = units.length; i < _i; i++) {
  43. const iu = inUnit(ctx, units[i], point, radius, minDist, maxDist, elementRadius);
  44. if (iu === Result.BelowMin) return Result.BelowMin;
  45. if (iu === Result.WithinMax) withinRange = true;
  46. }
  47. return withinRange ? Result.WithinMax : Result.Miss;
  48. }
  49. const distPivot = Vec3.zero();
  50. export function check(ctx: QueryContext, a: Structure, b: Structure, minDist: number, maxDist: number, elementRadius: QueryFn<number>) {
  51. if (a.elementCount === 0 || b.elementCount === 0) return 0;
  52. const { units } = a;
  53. let withinRange = false;
  54. ctx.element.structure = a;
  55. for (let i = 0, _i = units.length; i < _i; i++) {
  56. const unit = units[i];
  57. const { elements, conformation: { position } } = unit;
  58. ctx.element.unit = unit;
  59. for (let i = 0, _i = elements.length; i < _i; i++) {
  60. const e = elements[i];
  61. ctx.element.element = e;
  62. const tp = toPoint(ctx, b, position(e, distPivot), elementRadius(ctx), minDist, maxDist, elementRadius);
  63. if (tp === Result.BelowMin) return Result.BelowMin;
  64. if (tp === Result.WithinMax) withinRange = true;
  65. }
  66. }
  67. return withinRange;
  68. }
  69. }
  70. namespace MaxRadiusDist {
  71. const distVec = Vec3.zero();
  72. function inUnit(ctx: QueryContext, unit: Unit, p: Vec3, eRadius: number, maxDist: number, elementRadius: QueryFn<number>) {
  73. const { elements, conformation: { position } } = unit, dV = distVec;
  74. ctx.element.unit = unit;
  75. for (let i = 0, _i = elements.length; i < _i; i++) {
  76. const e = elements[i];
  77. ctx.element.element = e;
  78. if (Math.max(0, Vec3.distance(p, position(e, dV)) - eRadius - elementRadius(ctx)) <= maxDist) return true;
  79. }
  80. return false;
  81. }
  82. export function toPoint(ctx: QueryContext, s: Structure, point: Vec3, radius: number, maxDist: number, elementRadius: QueryFn<number>) {
  83. const { units } = s;
  84. for (let i = 0, _i = units.length; i < _i; i++) {
  85. if (inUnit(ctx, units[i], point, radius, maxDist, elementRadius)) return true;
  86. }
  87. return false;
  88. }
  89. const distPivot = Vec3.zero();
  90. export function check(ctx: QueryContext, a: Structure, b: Structure, maxDist: number, elementRadius: QueryFn<number>) {
  91. if (a.elementCount === 0 || b.elementCount === 0) return 0;
  92. const { units } = a;
  93. ctx.element.structure = a;
  94. for (let i = 0, _i = units.length; i < _i; i++) {
  95. const unit = units[i];
  96. ctx.element.unit = unit;
  97. const { elements, conformation: { position } } = unit;
  98. for (let i = 0, _i = elements.length; i < _i; i++) {
  99. const e = elements[i];
  100. ctx.element.element = e;
  101. if (toPoint(ctx, b, position(e, distPivot), elementRadius(ctx), maxDist, elementRadius)) return true;
  102. }
  103. }
  104. return false;
  105. }
  106. }