d-bl/GroundForge

Diagrams without distortion

Closed this issue · 6 comments

Intro

In a thread diagram, all nodes of a stitch start with the same coordinates. A force-graph algorithm separates them as shown below with a few snapshots of the animation. #119 fixed the worst bonnet like results.
afbeelding

Problems

  • Thread diagrams and animated pair diagrams are distorted towards the edges.
    They can be used to select patterns and stitches, but not as basis for a pricking.
  • The animations takes to much time / resources, even when only the end result is rendered.

@veronika suggested to replace the force graph with flat torus embedding to generate diagrams that don't distort. Her proof of concept uses a java library (ejml) to calculate the null-space and geometric pair diagram input. The branch mentioned below replaced part of the java code with scala code and uses topological thread diagram input.

Patterns with foot sides can become a tube but not a torus. Edit: V suggests to use an additional osculating pair. This appears to be an old technique as shown by a video of a machine dating from about 1930. Below a still as well as an example that serves our own purpose. With this constraint (adjustment to existing patterns) we can use the new algorithm for all patterns.

afbeelding

Branch without-distortion (under development)

Currently no main class is available. Use an IDE to run the test-class fte.BenchMark to create a set of patterns in target/test/fte-demo You may need to downgrade to java-8, for example from https://adoptopenjdk.net/releases.html

Sneak preview

The new web page (download) docs/pricking.html currently only shows a hard-coded pattern.

To do (by developers)

  • JavaScript call to calculate the null space, see lalolib issue lauerfab/MLweb#12 perhaps another library
    This issue blocks the sneak preview for non-developpers, see just above.
  • rewrite pricking.html to a mark-down file for the same layout (banner) as the help pages.
  • edit modes
    • changes strength/length of the connections between stitches
    • apply color codes to stitches (with a customizable legend?)
    • drop stitches
    • add stitches (the hardest to implement as user interaction involves two events selecting two line segments)
  • calculate vectors to repeat the tile for all patterns
  • fix patterns that fail for another reason
  • define parameter format for stitches to reproduce customized diagram.
  • Support overlapping tiles and compute the required patch size from shift arguments in the url-query. These shift argument define the translation vectors for the tiles in the prototype diagram.
  • color-code / over-under effect
  • support repeated twist and repeated cross
  • render isolated tiles with colored dots along the perimeter: the dance leader The green vectors show how to repeat, the new web page allows to change pin positions, though its by changing length rather than dragging pins around.

Currently more or less successful patterns from the Benchmark (once laolib is fixed)
image

I think we should use the scala linear algebra library called Breeze: https://github.com/scalanlp/breeze

Here is an example of how to use the library:

var A = new DenseMatrix(2, 2, Array(1.0, 0.0, 1.0, 1.0))
val svd.SVD(u, s, v) = svd(A)

In the svd result, s is a 1D array of values. Find entries in s that are 0 (or close to zero) and use those indices to select the corresponding v vectors. There should be two such v vectors, one will provide the x-values and the other the y-values for the layout (these are the null space).

See also:

https://stackoverflow.com/questions/39042333/how-to-solve-the-homogeneous-system-of-linear-equation-with-breeze

I'm afraid it is a plain scala library. I have no idea how much work it is to port it to scala-js, even just for the calls we need. So one challenge becomes two.

Sorry, I am confused. I thought a scala library is what you needed. Can you use a javascript library?

We need SVD (singular value decomposition). Something like svd.js might work: https://www.npmjs.com/package/svd-js

Scala-JS translates both to JVM (to run server side) and JavaScript (to run client side). Plain Scala translates only to JVM. I develop and test most of the code in a JVM environment. tiles.js binds the scala-js code to form events and form values. See readme - functional-contribution and use as ... library sections on that page.

So in a JVM environment I need a scala-library, on webpages I need a JavaScript library. Only few libraries are available for both.

I thought I saw something like SVD calls while debugging lolalib, I suppose ejml also has one. Wrappers around the SVD call of svd-js and ejmlbreeze might do the trick. Then we need to write the code to find the near-zero values just once.

I looked into the dependencies of breeze. It uses pure java libraries such as https://github.com/wendykierp/JTransforms so porting it to scala-js is a no go. Remains indeed the wrapper approach.

For EJML:

SimpleSVD svd = A.svd();

public T getW() Returns a diagonal matrix with the singular values. The singular values are ordered from largest to smallest.

public T getV() Returns the orthogonal 'V' matrix. Returns: An orthogonal n by n matrix.

So each column in the V matrix that corresponds to a 0 on the diagonal of the W matrix will give the same answer as obtained from svd.js.