Added Simantics/Diagram/{withScale,transformElement,transformElements} 20/2420/1
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Mon, 5 Nov 2018 23:54:38 +0000 (01:54 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Mon, 5 Nov 2018 23:54:38 +0000 (01:54 +0200)
Also added some documentation to the SCL module.

gitlab #179

Change-Id: Ia00785d38036f640c7636d53fdc7fde102c38d65

bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.md [new file with mode: 0644]
bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.scl
bundles/org.simantics.modeling/scl/Simantics/Diagram.md [new file with mode: 0644]
bundles/org.simantics.modeling/scl/Simantics/Diagram.scl

diff --git a/bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.md b/bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.md
new file mode 100644 (file)
index 0000000..118e2f6
--- /dev/null
@@ -0,0 +1,5 @@
+# Simantics/Diagram/ElementTransforms
+
+## Rotation
+
+::value[rotateToNeighborSlope]
index 9da7ee085ded29eff620f3582c5c937138df7702..3ea3aef3ba5bf008728322fec2ef49e11bd05cfc 100644 (file)
@@ -1,4 +1,18 @@
-import "Simantics/DB"
+module {
+    export = [rotateToNeighborSlope]
+}
+
+include "Simantics/DB"
+
+//-----------------------------------------------------------------------------
 
 importJava "org.simantics.diagram.elements.ElementTransforms" where
+    """
+        rotateToNeighborSlope element
+    
+    Rotates provided element so that its rotation is the same as the slope of a
+    line drawn between the two other elements the element is connected to.
+    
+    Note that this requires that the element is connected to exactly two other elements.
+    """
     rotateToNeighborSlope :: Resource -> <WriteGraph, Proc> Double 
diff --git a/bundles/org.simantics.modeling/scl/Simantics/Diagram.md b/bundles/org.simantics.modeling/scl/Simantics/Diagram.md
new file mode 100644 (file)
index 0000000..42dc5ca
--- /dev/null
@@ -0,0 +1,18 @@
+# Module Simantics/Diagram
+
+## Affine Transforms
+
+::data[Position]
+::value[location]
+::value[move]
+::value[rotate]
+::value[scale]
+::value[withScale]
+::value[flipX]
+::value[flipY]
+::value[positionToDoubleArray]
+::value[positionToVector]
+
+## Undocumented entities
+
+::undocumented[]
\ No newline at end of file
index 8276962eac7d4aefab138355327ee3d364cd3ffe..8dd1644e8d0737087eef7f67dc47c3751fd5c9a5 100644 (file)
@@ -24,16 +24,41 @@ type ConnectionType = Resource
 
 // --- Position -----------------------------------------------------
 
+"""
+    Position xx xy yx yy tx ty
+
+is a 2D affine transform with a rotation/scale/shear part,
+i.e. `xx xy yx yy` and a translation part `tx ty` which
+represents the matrix
+
+    [xx yx | tx]
+    [xy yy | ty]
+"""
 data Position = Position Double Double Double Double Double Double
 
 deriving instance Show Position
 
+"""
+    translation x y
+
+Returns an affine transform with identity rotation and `x y` for translation.
+"""
 location :: Double -> Double -> Position
 location x y = Position 1 0 0 1 x y
 
+"""
+    move (dx,dy)
+
+Returns a function that adds `(dx, dy)` to the translation of a specified affine transform.
+"""
 move :: (Double,Double) -> Position -> Position
 move (dx,dy) (Position xx xy yx yy x y) = Position xx xy yx yy (x+dx) (y+dy)
 
+"""
+    rotate n
+
+Returns a function that rotates the specified affine transform by `n*90` degrees
+"""
 rotate :: Integer -> Position -> Position
 rotate angle (Position xx xy yx yy x y) =
     Position (c*xx + s*xy) (c*xy - s*xx)
@@ -46,17 +71,68 @@ rotate angle (Position xx xy yx yy x y) =
     s = match a with 1 -> 1.0 ; 3 -> -1.0 ; _ -> 0.0
     c = match a with 0 -> 1.0 ; 2 -> -1.0 ; _ -> 0.0
 
+"""
+    scale s transform
+
+Multiplies the rotation part of the specified affine `transform` by `s`
+
+```
+[xx yx tx] => [s*xx s*yx tx]
+[xy yy ty]    [s*xy s*yy ty]
+```
+"""
 scale :: Double -> Position -> Position
 scale s (Position xx xy yx yy x y) = Position (s*xx) (s*xy) (s*yx) (s*yy) x y
 
+"""
+    withScale scale transform
+
+Sets the rotation part so that the base vectors defined by `u=[xx xy]` and `v=[yx yy]`
+are of length `scale`. This effectively sets the scaling of the elements without
+touching their rotation/shear.
+
+```
+su = scale / |u|
+sv = scale / |v|
+
+[xx yx tx] => [su*xx sv*yx tx]
+[xy yy ty]    [su*xy sv*yy ty]
+```
+"""
+withScale :: Double -> Position -> Position
+withScale scale (Position xx xy yx yy tx ty) = Position xx' xy' yx' yy' tx ty
+    where
+        su = scale / (sqrt (xx*xx + xy*xy))
+        sv = scale / (sqrt (yx*yx + yy*yy))
+        xx' = xx * su
+        xy' = xy * su
+        yx' = yx * sv
+        yy' = yy * sv
+
+"""
+    flipX transform
+
+Performs a mirror operation for the specified `transform` about the Y-axis.
+"""
 flipX :: Position -> Position
 flipX (Position xx xy yx yy x y) = Position (-xx) xy (-yx) yy x y 
 
+"""
+    flipY transform
+
+Performs a mirror operation for the specified `transform` about the X-axis.
+"""
 flipY :: Position -> Position
 flipY (Position xx xy yx yy x y) = Position xx (-xy) yx (-yy) x y
 
+"""
+Converts a [Position](#Position) into a `Vector Double`.
+"""
 positionToDoubleArray (Position a b c d e f) = toDoubleArray [a,b,c,d,e,f]
 
+"""
+Converts a [Position](#Position) into a `Vector Double`.
+"""
 positionToVector :: Position -> Vector Double
 positionToVector (Position a b c d e f) = runProc
     (do r = createMVector 6
@@ -142,6 +218,10 @@ deriving instance (Show res) => Show (DiagramElement res)
 
 // --- Functions ----------------------------------------------------
 
+@private
+transformOf element = Position (da!0) (da!1) (da!2) (da!3) (da!4) (da!5)
+    where da = fromDoubleArray $ relatedValue element DIA.HasTransform
+
 """Creates a random GUID L0.identifier property for the specified entity resource.""" 
 @private
 hasRandomIdentifier :: Resource -> <ReadGraph,WriteGraph> ()
@@ -727,10 +807,6 @@ elementsOfR diagram = filterJust $ map readElement'
     readRouteLine r = RouteLine
         (relatedValue r DIA.IsHorizontal) 
         (relatedValue r DIA.HasPosition)
-    transformOf element = do 
-        da = fromDoubleArray $
-            relatedValue element DIA.HasTransform
-        Position (da!0) (da!1) (da!2) (da!3) (da!4) (da!5)
     nameOf r = relatedValue r L0.HasName
     labelOf r = relatedValue2 r L0.HasLabel
     idOf r = match possibleObject r MOD.ElementToComponent with
@@ -806,6 +882,40 @@ getConnection diagram name = do
 
 setTransform :: Resource -> DoubleArray -> <WriteGraph> ()
 setTransform element transform = claimRelatedValueWithType element DIA.HasTransform G2D.Transform transform 
+
+"""
+    transformElement transformer element
+
+Performs the affine transformation encapsulated by `transformer` for the specified
+diagram `element`.
+
+For examples of possible transformer functions, see [scaleTransform](#scaleTransform)
+and [transformWithScale](#transformWithScale).
+"""
+transformElement :: (Position -> Position) -> Resource -> <WriteGraph> ()
+transformElement transformer element =
+    claimRelatedValue element DIA.HasTransform (positionToDoubleArray (transformer (transformOf element)))
+    
+"""
+    transformElements transformer elements
+
+Runs [transformElement](#transformElement) using the specified transformer for
+all the specified `elements`.
+
+Use this function together with e.g. [scaleTransform](#scaleTransform) and
+[transformWithScale](#transformWithScale) or similar functions.
+
+Examples:
+
+    import "Simantics/Diagram"
+
+    // Scale some elements by 1.5:
+    transformElements (scale 1.5) someElements
+    // Set scale of some elements to 10
+    transformElements (withScale 10) someElements
+"""
+transformElements :: (Position -> Position) -> [Resource] -> <WriteGraph> ()
+transformElements transformer elements = for elements $ transformElement transformer
     
 importJava "org.simantics.modeling.svg.CreateSVGElement" where
     createSVGElement :: Resource -> String -> ByteArray -> Double -> Double -> <WriteGraph> ()