Skip to content
Snippets Groups Projects
mesh.service.ts 4.36 KiB
Newer Older
import { Injectable, OnDestroy } from "@angular/core";
import { select, Store } from "@ngrx/store";
Xiao Gui's avatar
Xiao Gui committed
import { combineLatest, Observable, of } from "rxjs";
import { map, switchMap } from "rxjs/operators";
import { IMeshesToLoad } from '../constants'
Xiao Gui's avatar
Xiao Gui committed
import { selectorAuxMeshes } from "../store";
Xiao Gui's avatar
Xiao Gui committed
import { LayerCtrlEffects } from "../layerCtrl.service/layerCtrl.effects";
import { atlasSelection } from "src/state";
Xiao Gui's avatar
Xiao Gui committed
import { BaseService } from "../base.service/base.service";
import { IDS } from "src/atlasComponents/sapi"

/**
 * control mesh loading etc
 */

@Injectable()
export class NehubaMeshService implements OnDestroy {

  private onDestroyCb: (() => void)[] = []

  constructor(
Xiao Gui's avatar
Xiao Gui committed
    private store$: Store<any>,
Xiao Gui's avatar
Xiao Gui committed
    private effect: LayerCtrlEffects,
Xiao Gui's avatar
Xiao Gui committed
    private baseService: BaseService,
Xiao Gui's avatar
Xiao Gui committed
  ngOnDestroy(): void {
    while(this.onDestroyCb.length > 0) this.onDestroyCb.pop()()
  }

Xiao Gui's avatar
Xiao Gui committed
  public auxMeshes$ = this.effect.onATPDebounceNgLayers$.pipe(
Xiao Gui's avatar
Xiao Gui committed
    map(({ tmplAuxNgLayers }) => tmplAuxNgLayers),
Xiao Gui's avatar
Xiao Gui committed
  #allSegmentMeshes$ = this.baseService.completeNgIdLabelRegionMap$.pipe(
    map(record => {
      const ngIdRecord: Record<string, number[]> = {}

      for (const [ngId, labelToRegion] of Object.entries(record)) {
Xiao Gui's avatar
Xiao Gui committed
        for (const [label, ] of Object.entries(labelToRegion)) {
Xiao Gui's avatar
Xiao Gui committed
          if (!ngIdRecord[ngId]) {
            ngIdRecord[ngId] = []
Xiao Gui's avatar
Xiao Gui committed
          ngIdRecord[ngId].push(Number(label))
Xiao Gui's avatar
Xiao Gui committed
      }
Xiao Gui's avatar
Xiao Gui committed

Xiao Gui's avatar
Xiao Gui committed
      const arr: IMeshesToLoad[] = []
Xiao Gui's avatar
Xiao Gui committed

Xiao Gui's avatar
Xiao Gui committed
      for (const ngId in ngIdRecord) {
        const labelIndicies = ngIdRecord[ngId]
        arr.push({
          labelIndicies,
          layer: { name: ngId }
        })
      }

      return arr
    })
  )

  #selectedSegmentMeshes$ = combineLatest([
    this.baseService.completeNgIdLabelRegionMap$,
Xiao Gui's avatar
Xiao Gui committed
    this.store$.pipe(
Xiao Gui's avatar
Xiao Gui committed
      select(atlasSelection.selectors.selectedRegions),
    ),
  ]).pipe(
    switchMap(([record, selectedRegions]) => {
      const ngIdRecord: Record<string, number[]> = {}
      
      const selectedRegionNameSet = new Set(selectedRegions.map(r => r.name))

      for (const [ngId, labelToRegion] of Object.entries(record)) {
        for (const [label, region] of Object.entries(labelToRegion)) {
          if (!ngIdRecord[ngId]) {
            ngIdRecord[ngId] = []
Xiao Gui's avatar
Xiao Gui committed
          if (!selectedRegionNameSet.has(region.name)) {
            continue
Xiao Gui's avatar
Xiao Gui committed
          ngIdRecord[ngId].push(Number(label))
        }
      }

      const arr: IMeshesToLoad[] = []

      for (const ngId in ngIdRecord) {
        const labelIndicies = ngIdRecord[ngId]
        arr.push({
          labelIndicies,
          layer: { name: ngId }
        })
      }

      return of(arr)
    })
  )

  #auxMesh$ = this.store$.pipe(
    select(selectorAuxMeshes),
    switchMap(auxMeshes => {
      const obj: Record<string, number[]> = {}
      const arr: IMeshesToLoad[] = []
      for (const mesh of auxMeshes) {
        if (!obj[mesh.ngId]) {
          obj[mesh.ngId] = []
Xiao Gui's avatar
Xiao Gui committed
        if (mesh.visible) {
          obj[mesh.ngId].push(...mesh.labelIndicies)
Xiao Gui's avatar
Xiao Gui committed
      }
      for (const key in obj) {
        arr.push({
          layer: {
            name: key
          },
          labelIndicies: obj[key]
        })
      }
      return of(arr)
    })
  )

  public loadMeshes$: Observable<IMeshesToLoad> = combineLatest([
    this.#allSegmentMeshes$,
    this.#selectedSegmentMeshes$,
    this.#auxMesh$,
    this.store$.pipe(
      select(atlasSelection.selectors.selectedTemplate)
    ),
    this.store$.pipe(
      select(atlasSelection.selectors.selectedParcellation)
    )
Xiao Gui's avatar
Xiao Gui committed
  ]).pipe(
    switchMap(([ allSegMesh, selectedSegMesh, auxmesh, selectedTemplate, selectedParcellation ]) => {
      /**
       * TODO monkey patching jba29 in colin to show all meshes
       * 
       */
      if ((selectedParcellation.id === IDS.PARCELLATION.JBA29 || IDS.PARCELLATION.JBA30 === selectedParcellation.id) && selectedTemplate.id === IDS.TEMPLATES.COLIN27) {
        return of(...allSegMesh)
      }
Xiao Gui's avatar
Xiao Gui committed
      const hasSegSelected = selectedSegMesh.some(v => v.labelIndicies.length !== 0)
      const hasAuxMesh = auxmesh.length > 0
      const meshesToLoad: IMeshesToLoad[] = []
      if (!hasSegSelected) {
        meshesToLoad.push(
          ...(hasAuxMesh ? selectedSegMesh : allSegMesh),
          ...auxmesh,
        )
      } else {
        meshesToLoad.push(...selectedSegMesh, ...auxmesh)
      }
      return of(...meshesToLoad)
    })