private String transformationStr(Transformation trf) {
   NumberFormat fmt = FloatFormat.getInstance();
   Matrix matrix = trf.matrix();
   Vector vector = trf.vector();
   return "matrix <"
       + fmt.format(matrix.get(Transformation.X, Transformation.X))
       + ","
       + fmt.format(matrix.get(Transformation.Z, Transformation.X))
       + ","
       + fmt.format(matrix.get(Transformation.Y, Transformation.X))
       + ","
       + fmt.format(matrix.get(Transformation.X, Transformation.Z))
       + ","
       + fmt.format(matrix.get(Transformation.Z, Transformation.Z))
       + ","
       + fmt.format(matrix.get(Transformation.Y, Transformation.Z))
       + ","
       + fmt.format(matrix.get(Transformation.X, Transformation.Y))
       + ","
       + fmt.format(matrix.get(Transformation.Z, Transformation.Y))
       + ","
       + fmt.format(matrix.get(Transformation.Y, Transformation.Y))
       + ","
       + fmt.format(vector.getX())
       + ","
       + fmt.format(vector.getZ())
       + ","
       + fmt.format(vector.getY())
       + ">";
 }
  public void doWrite() {
    //		try {
    // some declarations in the POV file
    NumberFormat frm = FloatFormat.getInstance();

    // tree scale
    w.println(
        "#declare " + povrayDeclarationPrefix + "height = " + frm.format(tree.getHeight()) + ";");

    // leaf declaration
    if (tree.getLeafCount() != 0) writeLeafDeclaration();

    // stems
    progress.beginPhase("writing stem objects", tree.getStemCount());

    for (int level = 0; level < tree.getLevels(); level++) {

      w.println("#declare " + povrayDeclarationPrefix + "stems_" + level + " = union {");

      POVConeStemWriter writer = new POVConeStemWriter(this, /*params,*/ level);
      tree.traverseTree(writer);

      w.println("}");
    }

    // leaves
    if (tree.getLeafCount() != 0) {

      progress.beginPhase("writing leaf objects", tree.getLeafCount());

      w.println("#declare " + povrayDeclarationPrefix + "leaves = union {");

      POVConeLeafWriter lexporter = new POVConeLeafWriter(this, /*params*/ tree);
      tree.traverseTree(lexporter);

      w.println("}");

    } else { // empty declaration
      w.println("#declare " + povrayDeclarationPrefix + "leaves = sphere {<0,0,0>,0}");
    }

    progress.endPhase();

    // all stems together
    w.println("#declare " + povrayDeclarationPrefix + "stems = union {");
    for (int level = 0; level < tree.getLevels(); level++) {
      w.println("  object {" + povrayDeclarationPrefix + "stems_" + level + "}");
    }
    w.println("}");

    w.flush();

    //		} catch (Exception e) {
    //			e.printStackTrace();
    //			System.err.println(e);
    //			throw new ExportError(e.getMessage());
    //		}
  }
 private String vectorStr(Vector v) {
   NumberFormat fmt = FloatFormat.getInstance();
   return "<"
       + fmt.format(v.getX())
       + ","
       + fmt.format(v.getZ())
       + ","
       + fmt.format(v.getY())
       + ">";
 }
  /* (non-Javadoc)
   * @see net.sourceforge.arbaro.tree.TreeTraversal#enterStem(net.sourceforge.arbaro.tree.Stem)
   */
  public boolean enterStem(Stem stem) {
    if (level >= 0 && stem.getLevel() < level) {
      return true; // look further for stems

    } else if (level >= 0 && stem.getLevel() > level) {
      return false; // go back to higher level

    } else {

      String indent = whitespace(stem.getLevel() * 2 + 4);
      NumberFormat fmt = FloatFormat.getInstance();
      Enumeration sections = stem.sections();

      if (sections.hasMoreElements()) {
        StemSection from = (StemSection) sections.nextElement();
        StemSection to = null;

        while (sections.hasMoreElements()) {
          to = (StemSection) sections.nextElement();

          w.println(
              indent
                  + "cone   { "
                  + vectorStr(from.getPosition())
                  + ", "
                  + fmt.format(from.getRadius())
                  + ", "
                  + vectorStr(to.getPosition())
                  + ", "
                  + fmt.format(to.getRadius())
                  + " }");

          // put spheres where z-directions changes
          if (!from.getZ().equals(to.getPosition().sub(from.getPosition()).normalize())) {

            w.println(
                indent
                    + "sphere { "
                    + vectorStr(from.getPosition())
                    + ", "
                    + fmt.format(from.getRadius() - 0.0001)
                    + " }");
          }

          from = to;
        }

        // put sphere at stem end
        /* FIXME? now using sections instead of segments, the spherical stem end
        *       will be made from several cones instead of one shpere ...

        			if ((to.getRadius() > 0.0001) ||
        					(lpar.nTaper>1 && lpar.nTaper<=2))
        			{
        				w.println(indent + "sphere { " + vectorStr(to.getPosition()) + ", "
        						+ fmt.format(to.getRadius()-0.0001) + " }");
        			}
        		*/
      }

      exporter.incProgressCount(AbstractExporter.STEM_PROGRESS_STEP);

      return true;
    }
  }