Skip to content

Commit

Permalink
v10.4
Browse files Browse the repository at this point in the history
  • Loading branch information
mpeura committed Jan 17, 2025
1 parent 999fe35 commit 71e9355
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 167 deletions.
2 changes: 1 addition & 1 deletion demo/make-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ while (( $line <= iEnd )); do

arglast=( $cmd )
argcount=${#arglast[*]}
arglast=${arglast[$(( argpount - 1 ))]}
arglast=${arglast[$(( argcount - 1 ))]}
echo "arg last $arglast"
output=$arglast

Expand Down
123 changes: 123 additions & 0 deletions demo/test-svg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/bin/bash

DOCFILE=~/eclipse-workspace/rack/src/main/graphics.inc
TMPDIR=out
RACK="rack --outputPrefix \$PWD/$TMPDIR/ --outputConf svg:absolutePaths=true "

OUTFILES=()

mkdir -v --parents $TMPDIR

echo > $DOCFILE

function WRITE_DOC(){

if [ $# == 0 ]; then
# Read stdin
# WARNING: may hang?
cat >> $DOCFILE
else
# Write arguments
echo $* >> $DOCFILE
fi
# echo >> $DOCFILE
}

NEWLINE="
"

function RUN_TEST(){

local cmd="$RACK $*"
local args=( $* )
local argc=${#args[*]}

# Assume last arg is an output file
local OUTFILE=${args[$(( argc - 1 ))]}
local BASENAME=${OUTFILE%.*}
local FORMAT=${OUTFILE##*.}

# With original newlines, "\\\n"
# echo -e ${cmd//\/$TMPDIR/} > $TMPDIR/$BASENAME.cmd
# echo "# CMD: $TMPDIR/$BASENAME.cmd"
# rack_cmd=${cmd//\/$TMPDIR/}
rack_cmd=${cmd//\\/\\$NEWLINE }
echo "${rack_cmd}" > $TMPDIR/$BASENAME.cmd
cmd=(`echo -e $cmd | tr -d '\\'`)
#cmd=${cmd//\\/}
cmd="${cmd[*]}"
echo "# $cmd"
eval "${cmd}"
if [ $? != 0 ]; then
echo "# $cmd"
echo "Rack command failed"
exit 1
fi

echo "# Format $FORMAT "

if [ "$FORMAT" == "svg" ]; then

cmd="xmllint --noout $TMPDIR/$OUTFILE"
eval $cmd
if [ $? == 0 ]; then
echo "# OK: XML syntax"
else
echo $cmd
echo "# FAIL: XML syntax error (xmllint $OUTFILE) "
exit 2
fi

local OUTFILE_PNG=$BASENAME.png
cmd="inkscape $TMPDIR/$OUTFILE -o $TMPDIR/$OUTFILE_PNG"
eval $cmd

if [ $? == 0 ]; then
echo "# OK: created $TMPDIR/$OUTFILE_PNG"
OUTFILES+=($TMPDIR/$OUTFILE_PNG)
cp -v $TMPDIR/$OUTFILE_PNG ../doxygen/
else
echo $cmd
echo "# FAIL: SVG->PNG conversion "
exit 3
fi

CAPTION=${CAPTION:-"SVG output '$OUTFILE_PNG'"}

WRITE_DOC <<EOF
\code
$rack_cmd
\endcode
\image html $OUTFILE_PNG "$CAPTION"
\image latex $OUTFILE_PNG "$CAPTION" width=0.8\textwidth
EOF

unset CAPTION

fi
}



WRITE_DOC "Align two images horizontally (default)"
RUN_TEST \\ volume.h5 --cSize 400 -Q DBZH -c -o gray.png --palette 'default' -o rgb.png \\ -o simple.svg

WRITE_DOC "Also legend outputs (SVG) are included"
RUN_TEST \\ volume.h5 --cSize 400 -Q DBZH -c -o gray.png --palette 'default' -o rgb.png \\ --legendOut legend.svg \\ -o simple2.svg

WRITE_DOC 'With several inputs, it is handier to use \c --script . (See: \ref scripts .)'
WRITE_DOC 'Output names must be distinct, which is achieved using variables. (See \ref templates .)'
RUN_TEST \\ --script "'--cReset --cSize 300 -Q DBZH -c --palette \"\" -o out-\${NOD}.png'" \\ data/pvol_fi{anj,kor,kuo}.h5 -o triple1.svg

WRITE_DOC 'Variables identifying the radar and timestamp often distinguish files sufficiently.'
WRITE_DOC 'Hence, consider using variables like \c ${NOD} , \c ${what:date}, and \c ${what:time} .'
WRITE_DOC '\c Rack supports grouping output images to rows or columns. Use \c --cGroup to set a distinguishing key.'
RUN_TEST \\ --script "'--cReset --cSize 300 -Q DBZH -c --palette \"\" -o out-\${what:date}T\${what:time}-\${NOD}.png'" \\ --gGroup "'Test-\${NOD}'" \\ 'data-kiira/*.h5' -o series1.svg


WRITE_DOC 'In a grid of images, originating from several radars and times, the images can be labelled automatically with \c --gTitles command, with option \c IMAGE_TITLES . '
RUN_TEST \\ --script "'--cReset --cSize 300 -Q DBZH -c --palette \"\" -o out-\${what:date}T\${what:time}-\${NOD}.png'" \\ --gGroup "'Examples of \${PLC} (\${NOD}) on \${what:date|%Y/%m/%d}'" --gTitles IMAGE_TITLE \\ 'data-kiira/*.h5' -o series-labelled.svg

echo -e "Created: \ndisplay ${OUTFILES[*]}"
33 changes: 26 additions & 7 deletions src/drain/image/AlignSVG.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,22 +769,24 @@ DRAIN_ENUM_OSTREAM(LayoutSVG::GroupType);
struct AlignAdapterSVG : public AlignSVG {

/// Mark one of the elements of this object (SVG or G) as a decisive position
template <class T>
inline
void setAlignAnchor(const std::string & pathElem){
anchorHorz = pathElem;
anchorVert = pathElem;
void setAlignAnchor(const T & pathElem){
anchorVert = anchorHorz = getElem(pathElem);
updateAlign();
}

template <class T>
inline
void setAlignAnchorHorz(const std::string & pathElem){
anchorHorz = pathElem;
void setAlignAnchorHorz(const T & pathElem){
anchorHorz = getElem(pathElem);
updateAlign();
}

template <class T>
inline
void setAlignAnchorVert(const std::string & pathElem){
anchorVert = pathElem;
void setAlignAnchorVert(const T & pathElem){
anchorVert = getElem(pathElem);
updateAlign();
}

Expand All @@ -809,6 +811,23 @@ struct AlignAdapterSVG : public AlignSVG {

protected:

static inline
const std::string & getElem(const std::string &s){
return s;
};

static inline
const char * getElem(const char *s){
return s;
};

template <class T>
static inline
const std::string & getElem(const T & type){
return EnumDict<T>::dict.getKey(type, false);
}


virtual inline
void updateAlign() override {
updateAlignStr();
Expand Down
21 changes: 13 additions & 8 deletions src/drain/image/TreeUtilsSVG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace image {

PanelConfSVG TreeUtilsSVG::defaultConf;

//const std::set<svg::tag_t> TreeUtilsSVG::abstractTags = {
/*
const std::set<XML::intval_t> TreeUtilsSVG::abstractTags = {
svg::tag_t::STYLE,
svg::tag_t::DESC,
Expand All @@ -51,11 +51,14 @@ const std::set<XML::intval_t> TreeUtilsSVG::abstractTags = {
svg::tag_t::TITLE,
svg::tag_t::TSPAN,
};
*/

//bool TreeUtilsSVG::isAbstract(svg::tag_t tag){
/*
bool TreeUtilsSVG::isAbstract(XML::intval_t tag){
return (abstractTags.find((XML::intval_t)tag) != abstractTags.end());
}
*/



Expand Down Expand Up @@ -520,7 +523,7 @@ void TreeUtilsSVG::superAlign(TreeSVG & object, AlignBase::Axis orientation, Lay
*/

// mout.attention("ACCEPT:", object->getTag());
mout.special<LOG_NOTICE>(__FUNCTION__, " start: ", object.data); //, object->getId(), " -> ", object->getBoundingBox());
mout.special<LOG_DEBUG>(__FUNCTION__, " start: ", object.data); //, object->getId(), " -> ", object->getBoundingBox());


// Depth-first
Expand All @@ -529,7 +532,7 @@ void TreeUtilsSVG::superAlign(TreeSVG & object, AlignBase::Axis orientation, Lay
}

// mout.attention("ACCEPT:", object->getTag());
mout.special<LOG_NOTICE>(__FUNCTION__, " handle: ", object.data); //, object->getId(), " -> ", object->getBoundingBox());
mout.special<LOG_DEBUG>(__FUNCTION__, " handle: ", object.data); //, object->getId(), " -> ", object->getBoundingBox());


/// If main orientation (inside containers) is HORZ, stack containers VERT. And vice versa.
Expand Down Expand Up @@ -699,7 +702,8 @@ void TreeUtilsSVG::translateAll(TreeSVG & object, const Point2D<svg::coord_t> &
*/
int TranslatorSVG::visitPrefix(TreeSVG & tree, const TreeSVG::path_t & path) {
TreeSVG & node = tree(path);
if (TreeUtilsSVG::isAbstract((svg::tag_t)node->getType())){ // skip TITLE, DESC etc.
//if (TreeUtilsSVG::isAbstract((svg::tag_t)node->getType())){ // skip TITLE, DESC etc.
if (node->isAbstract()){ // skip TITLE, DESC etc.
return 1;
}
else {
Expand All @@ -723,12 +727,12 @@ bool TreeUtilsSVG::computeBoundingBox(const TreeSVG & elem, Box<svg::coord_t> &
// skip, trust others (rect anchor)
}
else {
if (box.empty()){
if (box.empty()){ // TODO: check/redefine empty
box = elem->getBoundingBox();
}
else {
// drain::Logger mout(__FILE__, __FUNCTION__);
//mout.pending("Updating bbox ", box, " with ", elem->getBoundingBox());
// mout.pending("Updating bbox ", box, " with ", elem->getBoundingBox());
box.expand(elem->getBoundingBox());
}
}
Expand All @@ -740,7 +744,7 @@ bool TreeUtilsSVG::computeBoundingBox(const TreeSVG & elem, Box<svg::coord_t> &

int BBoxRetrieverSVG::visitPrefix(TreeSVG & tree, const TreeSVG::path_t & path) {
TreeSVG & node = tree(path);
if (node->typeIs(svg::SVG) || node->typeIs(svg::GROUP)){
if (node->typeIs(svg::SVG, svg::GROUP)){
return 0; // continue (traverse children)
}
else {
Expand Down Expand Up @@ -793,7 +797,8 @@ int RelativePathSetterSVG::visitPrefix(TreeSVG & tree, const TreeSVG::path_t & p
drain::image::TreeSVG & imageNode = tree(path);
const std::string imagePath = imageNode->get("xlink:href");
if (drain::StringTools::startsWith(imagePath, dir)){
imageNode->set("xlink:href", imagePath.substr(dir.size())); // TODO: setURL ?
// imageNode->set("xlink:href", imagePath.substr(dir.size())); // TODO: setURL ?
imageNode->setUrl(imagePath.substr(dir.size()));
}
else {
// mout.attention("could not set relative path: ", p, " href:", imagePath);
Expand Down
34 changes: 3 additions & 31 deletions src/drain/image/TreeUtilsSVG.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,37 +74,15 @@ class FontSizes : public drain::UniTuple<double,4> {

struct PanelConfSVG {

/*
enum Axis {UNDEFINED_ORIENTATION=0, HORZ, VERT};
typedef drain::EnumFlagger<drain::SingleFlagger<Axis> > AxisFlagger;
AxisFlagger orientation = HORZ;
enum Direction {UNDEFINED_DIRECTION=0, INCR, DECR};
typedef drain::EnumFlagger<drain::SingleFlagger<Direction> > DirectionFlagger;
DirectionFlagger direction = INCR;
*/
// LayoutSVG layout;

/// SVG file may contain several "modules", for example rows or columns of IMAGE:s. This is the name of the current module, contained in a GROUP.
// Current
// std::string groupName;
// int maxPerGroup = 10;
bool absolutePaths = false;
bool absolutePaths = true;

// Currently, applications are recommended to handle "false" and "none". Or "auto"?
// std::string title;
// FontSizes fontSize;

/*
enum Legend {NO_LEGEND=0, LEFT=1, RIGHT=2, DUPLEX=LEFT|RIGHT, EMBED=4};
typedef drain::EnumFlagger<drain::MultiFlagger<Legend> > LegendFlagger;
LegendFlagger legend;
*/
//typedef drain::EnumFlagger<drain::SingleFlagger<Legend> > LegendFlagger;


inline // maxPerGroup(10), layout(Alignment::HORZ, LayoutSVG::INCR), legend(LEFT, EMBED),
PanelConfSVG() : absolutePaths(false){
PanelConfSVG() : absolutePaths(true){
}

/*
Expand Down Expand Up @@ -132,18 +110,12 @@ struct TreeUtilsSVG {
static PanelConfSVG defaultConf; // Consider separating Rack-specific properties.

/*
static
const std::set<svg::tag_t> abstractTags;
static
bool isAbstract(svg::tag_t tag);
*/

static
const std::set<XML::intval_t> abstractTags;
static
bool isAbstract(XML::intval_t tag);
*/

/// Compute bounding box of the whole structure.
/**
Expand Down
10 changes: 4 additions & 6 deletions src/drain/util/ReferenceMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,13 @@ class ReferenceMap2 : public SmartMap<T> {
inline
void unlink(const std::string & key){
map_t::erase(key);
// std::map<std::string,T>
/*
for (std::list<std::string>::iterator it = keyList.begin(); it != keyList.end(); ++it)
for (std::list<std::string>::iterator it = this->keyList.begin(); it != this->keyList.end(); ++it){
if (*it == key){
keyList.erase(it);
this->keyList.erase(it);
break;
}
unitMap.erase(key);
*/
}
//unitMap.erase(key);
}


Expand Down
4 changes: 4 additions & 0 deletions src/drain/util/XML.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ class XML : protected ReferenceMap2<FlexibleVariable> {
setText(StringBuilder<>(args...).str()); // str() to avoid infinite loop
}

inline
void setUrl(const std::string & s){
url = s;
}


// ---------------- Attributes ---------------
Expand Down
Loading

0 comments on commit 71e9355

Please sign in to comment.