http://mathling.com/shape  library module

http://mathling.com/shape


Common shape operations.

Copyright© Mary Holstege 2022-2023
CC-BY (https://creativecommons.org/licenses/by/4.0/)

June 2023
Status: Active

Imports

http://mathling.com/core/utilities
import module namespace util="http://mathling.com/core/utilities"
       at "../core/utilities.xqy"
http://mathling.com/geometric/rectangle
import module namespace box="http://mathling.com/geometric/rectangle"
       at "../geo/rectangle.xqy"
http://mathling.com/geometric
import module namespace geom="http://mathling.com/geometric"
       at "../geo/euclidean.xqy"
http://mathling.com/core/config
import module namespace config="http://mathling.com/core/config"
       at "../core/config.xqy"
http://mathling.com/core/errors
import module namespace errors="http://mathling.com/core/errors"
       at "../core/errors.xqy"
http://mathling.com/geometric/point
import module namespace point="http://mathling.com/geometric/point"
       at "../geo/point.xqy"

Functions

Function: scale-and-center
declare function scale-and-center($shapes as map(xs:string,item()*)*, $canvas as map(xs:string,item()*)) as map(xs:string,item()*)*


scale-and-center()
Scale the shapes and center them in the canvas so that they fill it.
You may need to snap or decimalize the results.

Params
  • shapes as map(xs:string,item()*)*: sequence of shapes
  • canvas as map(xs:string,item()*): space to fill
Returns
  • map(xs:string,item()*)*: the scaled and shifted shapes
declare function this:scale-and-center(
  $shapes as map(xs:string,item()*)*,
  $canvas as map(xs:string,item()*)
) as map(xs:string,item()*)*
{
  let $ccenter := box:center($canvas)
  let $bb := geom:bounding-box(geom:vertices($shapes))
  let $center := box:center($bb)
  let $scaling :=
    min((
      box:width($canvas) div box:width($bb),
      box:height($canvas) div box:height($bb)
    ))
  return (
    $shapes=>geom:mutate(
      function ($pt as map(xs:string,item()*)) as map(xs:string,item()*) {
        $pt=>
           geom:translate(-point:px($center),-point:py($center))=>
           geom:scale($scaling)=>
           geom:translate(point:px($ccenter), point:py($ccenter))
      }
    )
  )
}

Function: center
declare function center($shapes as map(xs:string,item()*)*, $canvas as map(xs:string,item()*)) as map(xs:string,item()*)*


center()
Center the shapes in the canvas without scaling.
You may need to snap or decimalize the results.

Params
  • shapes as map(xs:string,item()*)*: sequence of shapes
  • canvas as map(xs:string,item()*): space in which to center
Returns
  • map(xs:string,item()*)*: the shifted shapes
declare function this:center(
  $shapes as map(xs:string,item()*)*,
  $canvas as map(xs:string,item()*)
) as map(xs:string,item()*)*
{
  let $ccenter := box:center($canvas)
  let $bb := geom:bounding-box(geom:vertices($shapes))
  let $center := box:center($bb)
  return (
    $shapes=>geom:translate(
      point:px($ccenter) - point:px($center),
      point:py($ccenter) - point:py($center)
    )
  )
}

Original Source Code

xquery version "3.1";
(:~
 : Common shape operations.
 :
 : Copyright© Mary Holstege 2022-2023
 : CC-BY (https://creativecommons.org/licenses/by/4.0/)
 : @since June 2023
 : @custom:Status Active
 :)
module namespace this="http://mathling.com/shape"; 

import module namespace errors="http://mathling.com/core/errors"
       at "../core/errors.xqy";
import module namespace config="http://mathling.com/core/config"
       at "../core/config.xqy";
import module namespace util="http://mathling.com/core/utilities"
       at "../core/utilities.xqy";
import module namespace geom="http://mathling.com/geometric"
       at "../geo/euclidean.xqy";
import module namespace point="http://mathling.com/geometric/point"
       at "../geo/point.xqy";
import module namespace box="http://mathling.com/geometric/rectangle"
       at "../geo/rectangle.xqy";

declare namespace svg="http://www.w3.org/2000/svg";

declare namespace map="http://www.w3.org/2005/xpath-functions/map";
declare namespace array="http://www.w3.org/2005/xpath-functions/array";
declare namespace math="http://www.w3.org/2005/xpath-functions/math";

(:~
 : scale-and-center()
 : Scale the shapes and center them in the canvas so that they fill it.
 : You may need to snap or decimalize the results.
 :
 : @param $shapes: sequence of shapes
 : @param $canvas: space to fill
 : @return the scaled and shifted shapes
 :)
declare function this:scale-and-center(
  $shapes as map(xs:string,item()*)*,
  $canvas as map(xs:string,item()*)
) as map(xs:string,item()*)*
{
  let $ccenter := box:center($canvas)
  let $bb := geom:bounding-box(geom:vertices($shapes))
  let $center := box:center($bb)
  let $scaling :=
    min((
      box:width($canvas) div box:width($bb),
      box:height($canvas) div box:height($bb)
    ))
  return (
    $shapes=>geom:mutate(
      function ($pt as map(xs:string,item()*)) as map(xs:string,item()*) {
        $pt=>
           geom:translate(-point:px($center),-point:py($center))=>
           geom:scale($scaling)=>
           geom:translate(point:px($ccenter), point:py($ccenter))
      }
    )
  )
};

(:~
 : center()
 : Center the shapes in the canvas without scaling.
 : You may need to snap or decimalize the results.
 :
 : @param $shapes: sequence of shapes
 : @param $canvas: space in which to center
 : @return the shifted shapes
 :)
declare function this:center(
  $shapes as map(xs:string,item()*)*,
  $canvas as map(xs:string,item()*)
) as map(xs:string,item()*)*
{
  let $ccenter := box:center($canvas)
  let $bb := geom:bounding-box(geom:vertices($shapes))
  let $center := box:center($bb)
  return (
    $shapes=>geom:translate(
      point:px($ccenter) - point:px($center),
      point:py($ccenter) - point:py($center)
    )
  )
};