diff --git a/ggplotd-test-default b/ggplotd-test-default new file mode 100755 index 0000000..575e225 Binary files /dev/null and b/ggplotd-test-default differ diff --git a/source/ggplotd/geom.d b/source/ggplotd/geom.d index 03f557f..d2896e7 100644 --- a/source/ggplotd/geom.d +++ b/source/ggplotd/geom.d @@ -143,16 +143,30 @@ private template geomShape( string shape, AES ) } else { context.scale( width, height ); } - static if (shape=="triangle") + + static if (shape=="triangle") { context.moveTo( -0.5, -0.5 ); context.lineTo( 0.5, -0.5 ); context.lineTo( 0, 0.5 ); - } else static if (shape=="diamond") { + } else static if (shape=="diamond") + { context.moveTo( 0, -0.5 ); context.lineTo( 0.5, 0 ); context.lineTo( 0, 0.5 ); context.lineTo( -0.5, 0 ); + } else static if (shape=="cross" ) + { + context.moveTo( -0.5, -0.5 ); + context.lineTo( 0.5, 0.5 ); + context.moveTo( 0.5, -0.5 ); + context.lineTo( -0.5, 0.5 ); + } else static if (shape=="plus" ) + { + context.moveTo( -0.5, 0.0 ); + context.lineTo( 0.5, 0.0 ); + context.moveTo( 0.0, -0.5 ); + context.lineTo( 0.0, 0.5 ); } else { context.moveTo( -0.5, -0.5 ); context.lineTo( -0.5, 0.5 ); @@ -330,6 +344,28 @@ auto geomDiamond(AES)(AES aes) return geomShape!("diamond", AES)(aes); } +/** +Draw cross centered at given x,y location + +Aside from x and y also width and height are required. +If the type of width is of type Pixel (see aes.d) then dimensions are assumed to be in Pixel (not user coordinates). +*/ +auto geomCross(AES)(AES aes) +{ + return geomShape!("cross", AES)(aes); +} + +/** +Draw plus centered at given x,y location + +Aside from x and y also width and height are required. +If the type of width is of type Pixel (see aes.d) then dimensions are assumed to be in Pixel (not user coordinates). +*/ +auto geomPlus(AES)(AES aes) +{ + return geomShape!("plus", AES)(aes); +} + /// Create points from the data auto geomPoint(AES)(AES aesRange) { @@ -541,8 +577,6 @@ auto geomAxis(AES)(AES aesRaw, double tickLength, string label) import std.range : chain, empty, repeat; import std.math : sqrt, pow; - import ggplotd.range : mergeRange; - double[] xs; double[] ys; @@ -551,25 +585,29 @@ auto geomAxis(AES)(AES aesRaw, double tickLength, string label) double[] langles; string[] lbls; - auto merged = DefaultValues.mergeRange(aesRaw); - immutable toDir = - merged.find!("a.x != b.x || a.y != b.y")(merged.front).front; - auto direction = [toDir.x - merged.front.x, toDir.y - merged.front.y]; + aesRaw.find!("a.x != b.x || a.y != b.y")(aesRaw.front).front; + auto direction = [toDir.x - aesRaw.front.x, toDir.y - aesRaw.front.y]; immutable dirLength = sqrt(pow(direction[0], 2) + pow(direction[1], 2)); direction[0] *= tickLength / dirLength; direction[1] *= tickLength / dirLength; - while (!merged.empty) + import ggplotd.aes : hasAesField; + static if (hasAesField!(AES, "size")) + auto size = aesRaw.front.size; + else + auto size = DefaultValues.size; + + while (!aesRaw.empty) { - auto tick = merged.front; + auto tick = aesRaw.front; xs ~= tick.x; ys ~= tick.y; - merged.popFront; + aesRaw.popFront; // Draw ticks perpendicular to main axis; - if (xs.length > 1 && !merged.empty) + if (xs.length > 1 && !aesRaw.empty) { xs ~= [tick.x + direction[1], tick.x]; ys ~= [tick.y + direction[0], tick.y]; @@ -590,16 +628,17 @@ auto geomAxis(AES)(AES aesRaw, double tickLength, string label) import std.algorithm : map; import std.range : zip; - return xs.zip(ys).map!((a) => aes!("x", "y", "mask", "scale") - (a[0], a[1], false, false)).geomLine() - .chain( - lxs.zip(lys, lbls, langles) - .map!((a) => - aes!("x", "y", "label", "angle", "mask", "size", "scale") - (a[0], a[1], a[2], a[3], false, aesRaw.front.size, false )) - .geomLabel - ) - .chain( geomLabel(aesM) ); + return xs.zip(ys) + .map!((a) => aes!("x", "y", "mask", "scale",) (a[0], a[1], false, false)) + .geomLine + .chain( + lxs.zip(lys, lbls, langles) + .map!((a) => + aes!("x", "y", "label", "angle", "mask", "size", "scale") + (a[0], a[1], a[2], a[3], false, size, false )) + .geomLabel, + aesM.geomLabel + ); } /**