All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalismo.mesh.LineList.scala Maven / Gradle / Ivy

There is a newer version: 1.0-RC1
Show newest version
/*
 * Copyright 2015 University of Basel, Graphics and Vision Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package scalismo.mesh

import scalismo.common.PointId

final case class LineId(id: Int) extends AnyVal {
  def isValid: Boolean = this != LineId.invalid
}

object LineId {
  val invalid = LineId(-1)
}

object LineList {
  val empty = LineList(IndexedSeq.empty[LineCell])
}

/**
 * A list of lines that make up a poly line
 */
case class LineList(lines: IndexedSeq[LineCell]) {

  val pointIds = extractRange(lines)
  val lineIds = lines.indices.map(i => LineId(i))

  def line(id: LineId): LineCell = lines(id.id)

  /**
   * lines adjacent to each point
   */
  lazy val adjacentLinesForPoint: PointId => IndexedSeq[LineId] = {
    // list structure
    val emptyMapData = for (p <- pointIds) yield p -> collection.mutable.Set.empty[LineId]
    val lineMap = emptyMapData.toMap

    for (lineId <- lineIds) {
      val line = lines(lineId.id)
      lineMap(line.ptId1) += lineId
      lineMap(line.ptId2) += lineId
    }
    val data = lineMap.view.mapValues(s => s.toSet) // make immutable

    val dataSeq = IndexedSeq.tabulate(pointIds.size) { i =>
      data(pointIds(i)).toIndexedSeq
    }
    id => dataSeq(id.id)
  }

  /**
   *
   * points adjacent to a point
   */
  lazy val adjacentPointsForPoint: PointId => IndexedSeq[PointId] = {

    // all co-occurrences in line list: all points reachable by a link
    val emptyMapData = for (p <- pointIds) yield p -> collection.mutable.Set.empty[PointId]
    val pointMap = emptyMapData.toMap

    for (lineId <- lineIds) {
      val line = lines(lineId.id)
      pointMap(line.ptId1) ++= line.pointIds
      pointMap(line.ptId2) ++= line.pointIds
    }
    for (p <- pointIds) {
      pointMap(p) -= p
    }
    val mapData = pointMap.view.mapValues(s => s.toSet) // make immutable
    val seqData = IndexedSeq.tabulate(pointIds.size) { i =>
      mapData(pointIds(i)).toIndexedSeq
    }
    id => seqData(id.id)
  }

  /**
   * lines connected to a line via a common point
   *
   */
  lazy val adjecentLinesForLine: LineId => IndexedSeq[LineId] = {

    // for each line we get the 2 defining vertices, for each of those get all surrounding lines, remove self
    val emptyMapData = for (lineId <- lineIds) yield lineId -> collection.mutable.Set.empty[LineId]
    val lineMap = emptyMapData.toMap

    for (lineId <- lineIds) {
      lineMap(lineId) ++= lines(lineId.id).pointIds.flatMap(p => adjacentLinesForPoint(p))
      lineMap(lineId) -= lineId
    }
    val mapData = lineMap.view.mapValues(s => s.toSet)
    val seqData = IndexedSeq.tabulate(lineIds.size) { i =>
      mapData(lineIds(i)).toIndexedSeq
    }
    id => seqData(id.id)
  }

  /** points connected to a line, this information is contained in lines */
  lazy val adjacentPointsForLine: LineId => IndexedSeq[PointId] = { id =>
    line(id).pointIds
  }

  private[this] def extractRange(lines: IndexedSeq[LineCell]): IndexedSeq[PointId] = {
    if (lines.isEmpty) IndexedSeq[PointId]()
    else {
      val min = lines.flatMap(t => t.pointIds).minBy(_.id)
      val max = lines.flatMap(t => t.pointIds).maxBy(_.id)
      (min.id to max.id).map(id => PointId(id))
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy