Skip to content

Commit

Permalink
cherry picked clean-up from #143
Browse files Browse the repository at this point in the history
  • Loading branch information
jo-pol committed Jan 4, 2020
1 parent 9ac73da commit bf5971a
Show file tree
Hide file tree
Showing 7 changed files with 9 additions and 197 deletions.
82 changes: 1 addition & 81 deletions src/main/scala/dibl/Diagram.scala
Expand Up @@ -15,11 +15,9 @@
*/
package dibl

import dibl.LinkProps.WhiteStart

import scala.annotation.tailrec
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import scala.scalajs.js.annotation.{ JSExport, JSExportTopLevel }

@JSExportTopLevel("Diagram") case class Diagram(nodes: Seq[NodeProps],
links: Seq[LinkProps]
Expand Down Expand Up @@ -95,82 +93,4 @@ import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
.withFilter { case (_, t) => !targetsOfDuplicates.contains(t) }
.map { case (s, t) => (FindSource(s), t) }
}

/**
* Logs id,x,y values of the core node, and clockWise arranged sources and targets.
* The x/y are calculated back to col/row scale for readability.
*/
def logTileLinks(linkedNodes: Array[(NodeProps, Array[NodeProps])]): Unit = {
def log(n: NodeProps) = s"(id=${ n.id },x=${ n.x.toInt / 15 - 2 },y=${ n.y.toInt / 15 - 2 })"

linkedNodes.foreach { case (core, clockWise: Array[NodeProps]) =>
println(s"core${ log(core) } clockwise(${ clockWise.map(_.id).mkString(",") }) = ${ clockWise.map(log).mkString }")
}
}

/**
* Finds nodes within the boundaries and their connections in clockwise order.
*
* A node is a stitch, cross or twist. Links should never go up and have different directions.
* Tile boundaries (N/E/S/W) are inclusive. The values for these boundaries must be
* row/column numbers multiplied with the x/y scale for the diagram.
*
* @return nodes in random order, each mapped to their sources and targets in a clockwise order.
*/
def tileLinks(north: Double, east: Double, south: Double, west: Double): Seq[(NodeProps, Array[NodeProps])] = {
def inTile(node: NodeProps) = {
!node.pin &&
node.x >= west && node.x <= east &&
node.y >= north && node.y <= south
}

val sourceLinksForTileNodes = links.filter(link => inTile(nodes(link.target)))
val targetLinksForTileNodes = links.filter(link => inTile(nodes(link.source)))

def getSources(core: Int) = {
sourceLinksForTileNodes
.filter(_.target == core)
.sortBy(_.isInstanceOf[WhiteStart])
.map(_.source)
.map(nodes(_))
}

def getTargets(core: Int) = {
targetLinksForTileNodes
.filter(_.source == core)
.sortBy(_.isInstanceOf[WhiteStart])
.map(_.target)
.map(nodes(_))
}

// In thread diagrams each link has a short start or tail, as shown in ASCII art.
// Capitals visualize how the getSources/getTargets methods above order their nodes.
//
// cross twist
// source nodes: s2 s1 S1 S2
// / \
// \ / \ /
// \ /
// core node: \ /
// \ /
// / \ / \
// / \
// target nodes: t2 t1 T1 T2
//
// clockwise: s2,s1,t1,t2 s1,s2,t2,t1

sourceLinksForTileNodes.map(_.target).distinct.map { core =>
val coreNode = nodes(core)
val clockWise = coreNode.instructions match {
case "twist" => getSources(core) ++ getTargets(core).reverse
case "cross" => getSources(core).reverse ++ getTargets(core)
case _ => getSources(core)
// pairs never go up and are never on top of one another
// therefore delta-x can determine the order
.sortBy(n => n.x - coreNode.x) ++ getTargets(core)
.sortBy(n => coreNode.x - n.x)
}
coreNode -> clockWise.toArray // TODO drop toArray when no longer needed in a java context
}
}
}
9 changes: 6 additions & 3 deletions src/main/scala/dibl/NodeProps.scala
Expand Up @@ -57,11 +57,12 @@ case class NodeProps private(elems: Seq[(String, Any)]) extends Props {
val startOf: Int = m.getOrElse("startOf", "thread0").toString.replaceAll("thread", "").toInt

val pin: Boolean = m.getOrElse("pin", false).toString.toBoolean

val bobbin: Boolean = m.getOrElse("bobbin", false).toString.toBoolean

val stitch: Boolean = m.getOrElse("stitch", false).asInstanceOf[Boolean]

val isLeftTwist: Boolean = m.getOrElse("left", false).asInstanceOf[Boolean]
val isRightTwist: Boolean = m.getOrElse("right", false ).asInstanceOf[Boolean]

val cssClasses: String = (m.get("startOf"), m.get("thread")) match {
case (Some(_), _) =>
s"node threadStart"
Expand Down Expand Up @@ -104,7 +105,9 @@ object NodeProps {

def crossNode(id: String, suffix: Int) = NodeProps(Seq("title" -> title(id, suffix, "cross")))

def twistNode(id: String, suffix: Int) = NodeProps(Seq("title" -> title(id, suffix, "twist")))
def leftTwistNode(id: String, suffix: Int) = NodeProps(Seq("left"->true, "title" -> title(id, suffix, "twist")))

def rightTwistNode(id: String, suffix: Int) = NodeProps(Seq("right"->true, "title" -> title(id, suffix, "twist")))

def errorNode(tried: Try[_]) = NodeProps(Seq("title" -> tried.failed.get.getMessage, "bobbin" -> true))

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/dibl/Threads.scala
Expand Up @@ -49,7 +49,7 @@ case class Threads private
*/
def twistLeft(newNode: Int, stitchID: String, idSuffix: Int): (Threads, NodeProps, Seq[LinkProps]) =
(new Threads((newNode, newNode, n3, n4), (t2, t1, t3, t4)),
twistNode(stitchID, idSuffix),
leftTwistNode(stitchID, idSuffix),
twistedLinks(newNode, n1, n2, t1, t2))

/** moves the fourth thread over the third
Expand All @@ -58,7 +58,7 @@ case class Threads private
*/
def twistRight(newNode: Int, stitchID: String, idSuffix: Int): (Threads, NodeProps, Seq[LinkProps]) =
(new Threads((n1, n2, newNode, newNode), (t1, t2, t4, t3)),
twistNode(stitchID, idSuffix),
rightTwistNode(stitchID, idSuffix),
twistedLinks(newNode, n3, n4, t3, t4))

def leftPair: Threads = new Threads((n1, n2, n1, n2), (t1, t2, t1, t2))
Expand Down
42 changes: 0 additions & 42 deletions src/main/scala/dibl/proto/TilesConfig.scala
Expand Up @@ -189,48 +189,6 @@ import scala.scalajs.js.annotation.{ JSExport, JSExportTopLevel }
// rejoin links to ignored stitches
Item.cleanupIgnoredStitches(targetMatrix)

/**
* Get links for one tile.
*
* @param diagram A diagram created from this object.
* Use diagrams with the original nodes for transformation from pairs to threads to pairs etc.
* The result is not defined when using nodes with changed values for the x/y properties
* for any of the transformation steps. Plaits with more than 12 half stitches (ct)
* might cause a problem with duplicate ids in transformed diagrams.
* @param scale Use value one for the initial pair diagram,
* multiply by 2 for each transition from pair to thread diagram.
*
* Requirements:
* - The values for totalRows alias patchHeight respective totalCols alias patchWidth
* must add at least 4 rows/cols to the dimensions of the centerMatrix alias tile.
* - No gaps between tiles.
* - As for now: the leftMatrix and rightMatrix must be empty.
*
* @return An empty array on some types of invalid arguments, the type of error is logged to standard-out.
*
* Changes to the diagram won't affect previously returned results, nor the other way around.
*
* Node objects inside the tile are different from those outside the tile.
* Nodes outside the tile will have an id property shared by a node inside the tile on the
* opposite side. Where along the opposite side is defined by the four shift properties.
*
* Each transformation from pairs to threads puts more nodes at the same x/y positions.
* The start of their id-s will be identical, the tail of their id-s will be different.
*/
@JSExport
def linksOfCenterTile(diagram: Diagram, scale: Int): Array[(NodeProps, Array[NodeProps])] = {
val links: Seq[(NodeProps, Array[NodeProps])] = boundsForTileLinks match {
case (0,0,0,0) => Seq.empty
case (n, e, s, w) => diagram.tileLinks(n * 15 * scale, e * 15 * scale, s * 15 * scale, w * 15 * scale)
}
if (links.exists{link =>
// safeguard against invalid results
val (core, clockWise) = link
core.id.isEmpty || clockWise.length != 4
}) Seq.empty
else links
}.toArray

/**
* @param scale Use value 15 for the initial pair diagram,
* multiply by 2 for each transition from pair to thread diagram.
Expand Down
10 changes: 0 additions & 10 deletions src/test/scala/Demo4Java.java
Expand Up @@ -98,16 +98,6 @@ private static Diagram writeNudgedDiagram(String fileName, String strokeWidth, D
TilesConfig config, Integer scale) throws IOException {
// System.out.println("-------------- " + fileName);

// needs original positions without any nudging applied to previous diagrams
Tuple2<NodeProps, NodeProps[]>[] linkedNodes = config.linksOfCenterTile(diagram, scale);
diagram.logTileLinks(linkedNodes);
if (linkedNodes.length > 0) {
// TODO compute deltas from logged data
// showing how to access
String coreId = linkedNodes[0]._1().id();
String firstLinkId = linkedNodes[0]._2()[0].id();
}

int nrOfNodes = diagram.nodes().size();
double[][] locations = new double[nrOfNodes][2];
for (int i = 0; i < nrOfNodes; i++) {
Expand Down
Binary file removed src/test/scala/dibl/TileLinksSpec.png
Binary file not shown.
59 changes: 0 additions & 59 deletions src/test/scala/dibl/TileLinksSpec.scala

This file was deleted.

0 comments on commit bf5971a

Please sign in to comment.