Skip to content

Commit

Permalink
#2750 - Fix unselected end of the selected bond to be the center
Browse files Browse the repository at this point in the history
  • Loading branch information
yuleicul committed Jun 8, 2023
1 parent eb2fd76 commit 0a0a034
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 208 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { fromRGroupFragment, fromUpdateIfThen } from './rgroup'

import { Action } from './action'
import { fromAtomsFragmentAttr } from './atom'
import { getRelSgroupsBySelection } from './utils'
import { getRelSGroupsBySelection } from './utils'

export function fromMultipleMove(restruct, lists, d) {
d = new Vec2(d)
Expand Down Expand Up @@ -84,7 +84,7 @@ export function fromMultipleMove(restruct, lists, d) {
})

if (lists.sgroupData && lists.sgroupData.length === 0) {
const sgroups = getRelSgroupsBySelection(restruct, lists.atoms)
const sgroups = getRelSGroupsBySelection(struct, lists.atoms)
sgroups.forEach((sg) => {
action.addOp(new SGroupDataMove(sg.id, d))
})
Expand Down
199 changes: 37 additions & 162 deletions packages/ketcher-core/src/application/editor/actions/rotate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,9 @@ import {
SGroupDataMove,
TextMove
} from '../operations'
import { Bond, Fragment, Pile, Vec2 } from 'domain/entities'
import { Bond, Fragment, Struct, Vec2 } from 'domain/entities'
import { ReStruct } from 'application/render'
import {
getRelSgroupsBySelection,
structSelection,
isAttachmentBond
} from './utils'
import { getRelSGroupsBySelection, structSelection } from './utils'
import { Action } from './action'
import { Selection } from '../editor.types'

Expand Down Expand Up @@ -153,182 +149,61 @@ function fromTextFlip(
}

function fromStructureFlip(
restruct: ReStruct,
reStruct: ReStruct,
selection: Selection | null,
dir: FlipDirection,
flipDirection: FlipDirection,
center: Vec2
) {
const struct = restruct.molecule

const struct = reStruct.molecule
const action = new Action()

if (!selection) {
selection = structSelection(struct)
}

if (!selection.atoms) {
return action.perform(restruct)
}

const fids = selection.atoms.reduce((acc, aid) => {
const atom = struct.atoms.get(aid)

selection?.atoms?.forEach((atomId) => {
const atom = struct.atoms.get(atomId)
if (!atom) {
return acc
}

if (!acc[atom.fragment]) {
acc[atom.fragment] = []
return
}

acc[atom.fragment].push(aid)
return acc
}, {})

const fidsNumberKeys = Object.keys(fids).map((frag) => parseInt(frag, 10))

const isFragFound = fidsNumberKeys.find((frag) => {
const allFragmentsOfStructure = struct.getFragmentIds(frag)
const selectedFragmentsOfStructure = new Pile(fids[frag])
const res = allFragmentsOfStructure.equals(selectedFragmentsOfStructure)
return !res
const difference = flipPointByCenter(atom.pp, center, flipDirection)
action.addOp(new AtomMove(atomId, difference))
})

if (typeof isFragFound === 'number') {
return flipPartOfStructure({
fids,
struct,
restruct,
dir,
action,
selection
})
}

return flipStandaloneStructure({
fids,
struct,
restruct,
center,
dir,
action,
selection
const sGroups = getRelSGroupsBySelection(struct, selection?.atoms || [])
sGroups.forEach((sGroup) => {
if (!sGroup.pp) {
return
}
const difference = flipPointByCenter(sGroup.pp, center, flipDirection)
action.addOp(new SGroupDataMove(sGroup.id, difference))
})
}

function getRotationPoint(struct, selection) {
const { bonds } = struct
const isSelectedAtom = (atomId) => selection.atoms.includes(atomId)
const getAttachmentBond = () => {
for (const [bondId, bond] of bonds.entries()) {
if (isAttachmentBond(bond, selection)) {
return [bondId, bond]
}
}
return [null, null]
if (selection?.bonds) {
flipBonds(selection.bonds, struct, action)
}
const getRotationPointAtomId = (attachmentBondId, attachmentBond) => {
if (selection.bonds.includes(attachmentBondId)) {
return [attachmentBond.begin, attachmentBond.end].find(
(atomId) => !isSelectedAtom(atomId)
)
}
return [attachmentBond.begin, attachmentBond.end].find(isSelectedAtom)
}

const [attachmentBondId, attachmentBond] = getAttachmentBond()
const rotationPointAtomId = getRotationPointAtomId(
attachmentBondId,
attachmentBond
)
return struct.atoms.get(rotationPointAtomId).pp
}

function flipBonds(selection, struct, action) {
if (selection.bonds) {
selection.bonds.forEach((bid) => {
const bond = struct.bonds.get(bid)

if (bond.type !== Bond.PATTERN.TYPE.SINGLE) {
return
}

if (bond.stereo === Bond.PATTERN.STEREO.UP) {
action.addOp(new BondAttr(bid, 'stereo', Bond.PATTERN.STEREO.DOWN))
return
}

if (bond.stereo === Bond.PATTERN.STEREO.DOWN) {
action.addOp(new BondAttr(bid, 'stereo', Bond.PATTERN.STEREO.UP))
}
})
}
return action.perform(reStruct)
}

function flipPartOfStructure({
fids,
struct,
restruct,
dir,
action,
selection
}) {
const rotationPoint = getRotationPoint(struct, selection)

Object.keys(fids).forEach((frag) => {
const fragment = new Pile(fids[frag])
function flipBonds(bondIds: number[], struct: Struct, action: Action) {
bondIds.forEach((bondId) => {
const bond = struct.bonds.get(bondId)

fragment.forEach((aid) => {
const atom = struct.atoms.get(aid)
const d = flipPointByCenter(atom.pp, rotationPoint, dir)
action.addOp(new AtomMove(aid, d))
})

const sgroups = getRelSgroupsBySelection(restruct, Array.from(fragment))
sgroups.forEach((sg) => {
const d = flipPointByCenter(sg.pp, rotationPoint, dir)
action.addOp(new SGroupDataMove(sg.id, d))
})
})

flipBonds(selection, struct, action)
if (!bond) {
return
}

return action.perform(restruct)
}
if (bond.type !== Bond.PATTERN.TYPE.SINGLE) {
return
}

function flipStandaloneStructure({
fids,
struct,
restruct,
center,
dir,
action,
selection
}) {
Object.keys(fids).forEach((frag) => {
const fragment = new Pile(fids[frag])

const bbox = struct.getCoordBoundingBox(fragment)
const calcCenter =
center ||
new Vec2((bbox.max.x + bbox.min.x) / 2, (bbox.max.y + bbox.min.y) / 2)

fragment.forEach((aid) => {
const atom = struct.atoms.get(aid)
const d = flipPointByCenter(atom.pp, calcCenter, dir)
action.addOp(new AtomMove(aid, d))
})
if (bond.stereo === Bond.PATTERN.STEREO.UP) {
action.addOp(new BondAttr(bondId, 'stereo', Bond.PATTERN.STEREO.DOWN))
return
}

const sgroups = getRelSgroupsBySelection(restruct, Array.from(fragment))
sgroups.forEach((sg) => {
const d = flipPointByCenter(sg.pp, calcCenter, dir)
action.addOp(new SGroupDataMove(sg.id, d))
})
if (bond.stereo === Bond.PATTERN.STEREO.DOWN) {
action.addOp(new BondAttr(bondId, 'stereo', Bond.PATTERN.STEREO.UP))
}
})

flipBonds(selection, struct, action)

return action.perform(restruct)
}

function flipPointByCenter(
Expand Down Expand Up @@ -369,7 +244,7 @@ export function fromRotate(restruct, selection, center, angle) {
})

if (!selection.sgroupData) {
const sgroups = getRelSgroupsBySelection(restruct, selection.atoms)
const sgroups = getRelSGroupsBySelection(struct, selection.atoms)

sgroups.forEach((sg) => {
action.addOp(
Expand Down
11 changes: 7 additions & 4 deletions packages/ketcher-core/src/application/editor/actions/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
***************************************************************************/

import { AtomAttributes, Bond, Vec2 } from 'domain/entities'
import { AtomAttributes, Bond, Struct, Vec2 } from 'domain/entities'

import closest from '../shared/closest'
import { difference } from 'lodash'
Expand Down Expand Up @@ -189,16 +189,19 @@ export function atomForNewBond(restruct, id, bond?) {
return { atom: a, pos: v }
}

export function getRelSgroupsBySelection(restruct, selectedAtoms) {
return restruct.molecule.sgroups.filter(
export function getRelSGroupsBySelection(
struct: Struct,
selectedAtoms: number[]
) {
return struct.sgroups.filter(
(_sgid, sg) =>
!sg.data.attached &&
!sg.data.absolute &&
difference(sg.atoms, selectedAtoms).length === 0
)
}

export function isAttachmentBond({ begin, end }: Bond, selection): boolean {
export function isAttachmentBond({ begin, end }: Bond, selection: Selection) {
if (!selection.atoms) {
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class RotateController {
this.editor
)

const { texts, rxnArrows, rxnPluses } = this.editor.selection() || {}
const { texts, rxnArrows, rxnPluses, bonds } = this.editor.selection() || {}

const isMoreThanOneItemBeingSelected =
visibleAtoms.concat(texts || [], rxnArrows || [], rxnPluses || [])
Expand All @@ -166,7 +166,8 @@ class RotateController {
visibleAtoms,
texts,
rxnArrows,
rxnPluses
rxnPluses,
bonds
)

this.handleCenter = new Vec2(
Expand Down Expand Up @@ -260,7 +261,8 @@ class RotateController {
visibleAtoms: number[],
texts?: number[],
rxnArrows?: number[],
rxnPluses?: number[]
rxnPluses?: number[],
bonds?: number[]
) {
const RECT_RADIUS = 20
const RECT_PADDING = 10
Expand All @@ -271,10 +273,12 @@ class RotateController {
texts,
rxnArrows,
rxnPluses,

sgroups: getGroupIdsFromItemArrays(this.render.ctab.molecule, {
atoms: visibleAtoms
})
})!
}),
bonds
})
.transform(Scale.obj2scaled, this.render.options)
.translate(this.render.options.offset || new Vec2())

Expand Down
Loading

0 comments on commit 0a0a034

Please sign in to comment.