PDFlib
BASKET
PDFlib

graphics/aligned_path_objects

Create a schematic street map from line and ring segments. The line segments can have arbitrary length, the ring segments can have arbitrary radius and angle. This is implemented with path objects. By using named points and the "attachmentpoint" and "align" options the positioning of the segments in a seamless fashion is very easy.

Download Java Code     Show Output PDF 

/*

 * $Id: aligned_path_objects.java,v 1.7 2010/02/15 08:32:03 stm Exp $

 *

 * Aligned path objects

 *

 * Create a schematic street map from line and ring segments. The line segments

 * can have arbitrary length, the ring segments can have arbitrary radius and

 * angle. This is implemented with path objects. By using named points and

 * the "attachmentpoint" and "align" options the positioning of the segments

 * in a seamless fashion is very easy.

 *

 * Required software: PDFlib/PDFlib+PDI/PPS 8

 * Required data: none

 */

package com.pdflib.cookbook.pdflib.graphics;


import com.pdflib.pdflib;

import com.pdflib.PDFlibException;


public class aligned_path_objects {


    /**

     * The basic unit in points.

     */

    final static double BU = 20;


    /**

     * Size of the circle for the reference point.

     */

    final static double REF_POINT_SIZE = BU / 20;


    /**

     * The page width

     */

    final static double PG_WIDTH = 11 * BU;


    /**

     * The page height

     */

    final static double PG_HEIGHT = 11 * BU;


    /**

     * The street width in basic units.

     */

    final static double STREET_WIDTH = 0.15;

   

    /**

     * The pdflib object

     */

    private pdflib p;


    private interface segment {

        public int create_path() throws PDFlibException;

    }


    private class ring_segment implements segment {

        ring_segment(double radius, double phi) {

            this.radius = radius;

            this.phi = phi;

        }


        /**

         * Create a path for a ring segment using polar coordinates. A positive

         * angle means a turn to the left, a negative angle means a turn to the

         * right.

         */

        public int create_path() throws PDFlibException {

            double r1 = radius * BU;

            double r2 = (radius + STREET_WIDTH) * BU;

            double psi = 0;

           

            /*

             * Ring with phi > 0 is constructed in the first quadrant.

             * Ring with phi < 0 is constructed in the fourth quadrant:

             * Rotation through -180.

             */

            if (phi < 0) {

                final double rad = r1;

                r1 = r2;

                r2 = rad;

                psi = -180;

            }

           

            int path = p.add_path_point(-1, r1, psi, "move", "polar name=pivot");

            p.add_path_point(path, r1, psi + phi / 2, "control", "polar");

            p.add_path_point(path, r1, psi + phi, "circular",

                    "polar name=attach");

            p.add_path_point(path, r2, psi + phi, "line", "polar name=dir");

            p.add_path_point(path, r2, psi + phi / 2, "control", "polar");

            p.add_path_point(path, r2, psi, "circular", "polar");


            return path;

        }


        double radius;

        double phi;

    }


    private class line_segment implements segment {

        line_segment(double length) {

            this.length = length;

        }


        /**

         * Create a path for a line segment.

         */

        public int create_path() throws PDFlibException {

            final double l = length * BU;

            final double w = STREET_WIDTH * BU;


            int path = p.add_path_point(-1, 0, 0, "move", "name=pivot");

            p.add_path_point(path, 0, l, "line", "name=attach");

            p.add_path_point(path, w, l, "line", "name=dir");

            p.add_path_point(path, w, 0, "line", "");


            return path;

        }


        double length;

    }


    private void run() {

        /* This is where the data files are. Adjust if necessary. */

        final String searchpath = "../input";

        final String outfile = "aligned_path_objects.pdf";

        final String title = "Aligned path objects";


        try {

            p = new pdflib();


            p.set_parameter("SearchPath", searchpath);


            p.set_parameter("errorpolicy", "exception");


            if (p.begin_document(outfile, "") == -1)

                throw new Exception("Error: " + p.get_errmsg());


            p.set_info("Creator", "PDFlib Cookbook");

            p.set_info("Title", title + " $Revision: 1.7 $");


            p.begin_page_ext(PG_WIDTH, PG_HEIGHT, "");


            /*

             * Description

             */

            String optlist = "fontname=Helvetica encoding=unicode "

                + "fontsize=" + BU / 2;


            p.fit_textline("Aligned path objects", 2 * BU, PG_HEIGHT - 2 * BU,

                optlist);


            final segment segments[] = {

                        new line_segment(4.5),

                new ring_segment(0.5, -70),

                new line_segment(3.5),

                new ring_segment(0.2, -135),

                new line_segment(0.5),

                new ring_segment(0.1, 35),

                new ring_segment(7, 80),

                new ring_segment(0.1, -170),

                new line_segment(3),

                new ring_segment(0.5, -60),

                new line_segment(2.5),

                new ring_segment(0.1, 90),

                new ring_segment(1.2, 60),

                new ring_segment(0.3, -100),

                new line_segment(2.5),

                new ring_segment(0.3, -80),

                new line_segment(1.5),

                new ring_segment(0.15, 160),

                new line_segment(0.7),

                new ring_segment(0.15, 60),

                new ring_segment(0.15, -40),

                new line_segment(0.6),

                new ring_segment(0.15, -85),

                new line_segment(0.755),

                new ring_segment(0.15, -104),

                new line_segment(0.99),

            };


            /*

             * Initial direction

             */

            double dx = 0.469;

            double dy = 0.883;

            String align_opt = "align={" + dx + " " + dy + "}";


            /*

             * Start point

             */

            final double startx = 4.7 * BU;

            final double starty = 1 * BU;


            double x = startx;

            double y = starty;


            /*

             * Loop over segments and draw them one by one

             */

            int i;

            int path;

            for (i = 0, path = -1; i < segments.length; i += 1) {

                if (path != -1) {

                    /*

                     * Compute the coordinates of the next pivot point

                     */

                    final double xatt = p.info_path(path, "px", align_opt

                        + " attachmentpoint=pivot name=attach");

                    final double yatt = p.info_path(path, "py", align_opt

                        + " attachmentpoint=pivot name=attach");


                    /*

                     * Compute the new alignment vector

                     */

                    final double xdir = p.info_path(path, "px",

                            align_opt + " attachmentpoint=pivot name=dir");

                    final double ydir = p.info_path(path, "py",

                            align_opt + " attachmentpoint=pivot name=dir");

                    dx = xdir - xatt;

                    dy = ydir - yatt;

                    align_opt = "align={" + dx + " " + dy + "}";


                    /*

                                         * New reference vector

                                         */

                    x += xatt;

                    y += yatt;

                   

                    /*

                     * Get rid of previous path

                     */

                    p.delete_path(path);

                }


                /*

                 * Create the path object and draw the path, taking the "pivot"

                 * point as attachment point and aligned to the alignment

                 * vector.

                 */

                path = segments[i].create_path();


                p.draw_path(path, x, y,

                    align_opt + " fillcolor=white attachmentpoint=pivot "

                        + "close stroke fill linewidth=0.5");


                /*

                 * Mark the pivot point

                 */

                p.setcolor("fill", "red", 0, 0, 0, 0);

                p.circle(x, y, REF_POINT_SIZE / 2);

                p.fill();

            }


            /*

             * Delete last path object

             */

            if (path != -1) {

                p.delete_path(path);

            }


            /*

             * Redraw the first pivot point on top

             */

            p.setcolor("fill", "red", 0, 0, 0, 0);

            p.circle(startx, starty, REF_POINT_SIZE / 2);

            p.fill();


            p.end_page_ext("");

            p.end_document("");

        }

        catch (PDFlibException e) {

            System.err.print("PDFlib exception occurred:\n");

            System.err.print("[" + e.get_errnum() + "] " + e.get_apiname()

                + ": " + e.get_errmsg() + "\n");

        }

        catch (Exception e) {

            System.err.println(e.getMessage());

        }

        finally {

            if (p != null) {

                p.delete();

            }

        }

    }


    public static void main(String argv[]) {

        aligned_path_objects instance = new aligned_path_objects();

        instance.run();

    }

}