From: Tuukka Lehtonen Date: Mon, 5 Nov 2018 23:54:38 +0000 (+0200) Subject: Added Simantics/Diagram/{withScale,transformElement,transformElements} X-Git-Tag: v1.43.0~136^2~296 X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=b8afde7d56558ae67a5821c066e0ea0f69b049da Added Simantics/Diagram/{withScale,transformElement,transformElements} Also added some documentation to the SCL module. gitlab #179 Change-Id: Ia00785d38036f640c7636d53fdc7fde102c38d65 --- 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 index 000000000..118e2f6c9 --- /dev/null +++ b/bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.md @@ -0,0 +1,5 @@ +# Simantics/Diagram/ElementTransforms + +## Rotation + +::value[rotateToNeighborSlope] diff --git a/bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.scl b/bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.scl index 9da7ee085..3ea3aef3b 100644 --- a/bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.scl +++ b/bundles/org.simantics.diagram/scl/Simantics/Diagram/ElementTransforms.scl @@ -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 -> 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 index 000000000..42dc5ca42 --- /dev/null +++ b/bundles/org.simantics.modeling/scl/Simantics/Diagram.md @@ -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 diff --git a/bundles/org.simantics.modeling/scl/Simantics/Diagram.scl b/bundles/org.simantics.modeling/scl/Simantics/Diagram.scl index 8276962ea..8dd1644e8 100644 --- a/bundles/org.simantics.modeling/scl/Simantics/Diagram.scl +++ b/bundles/org.simantics.modeling/scl/Simantics/Diagram.scl @@ -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 -> () @@ -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 -> () 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 -> () +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] -> () +transformElements transformer elements = for elements $ transformElement transformer importJava "org.simantics.modeling.svg.CreateSVGElement" where createSVGElement :: Resource -> String -> ByteArray -> Double -> Double -> ()