BASKET
Search
PDFlib

graphics/aligned_path_objects

Download Java Code       Switch to PHP Code     Show Output PDF

/*

 * $Id: aligned_path_objects.java,v 1.10 2014/01/30 14:05:25 rjs 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 9

 * 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";

        int exitcode = 0;


        try {

            p = new pdflib();


            p.set_option("searchpath={" + searchpath + "}");


            p.set_option("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.10 $");


            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");

            exitcode = 1;

        }

        catch (Exception e) {

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

            exitcode = 1;

        }

        finally {

            if (p != null) {

                p.delete();

            }

            System.exit(exitcode);

        }

    }


    public static void main(String argv[]) {

        aligned_path_objects instance = new aligned_path_objects();

        instance.run();

    }

}