fr.ign.cogit.geoxygene.appli.render.primitive.LinePrimitiveRenderer.java Source code

Java tutorial

Introduction

Here is the source code for fr.ign.cogit.geoxygene.appli.render.primitive.LinePrimitiveRenderer.java

Source

/*******************************************************************************
 * This file is part of the GeOxygene project source files.
 * 
 * GeOxygene aims at providing an open framework which implements OGC/ISO
 * specifications for the development and deployment of geographic (GIS)
 * applications. It is a open source contribution of the COGIT laboratory at the
 * Institut Gographique National (the French National Mapping Agency).
 * 
 * See: http://oxygene-project.sourceforge.net
 * 
 * Copyright (C) 2005 Institut Gographique National
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library (see file LICENSE if present); if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307 USA
 *******************************************************************************/

package fr.ign.cogit.geoxygene.appli.render.primitive;

import javax.swing.JDialog;
import javax.vecmath.Point2d;
import javax.vecmath.Vector2d;

import org.apache.log4j.Logger;
import org.lwjgl.opengl.GL11;

import fr.ign.cogit.geoxygene.appli.Viewport;
import fr.ign.cogit.geoxygene.appli.gl.TiledTexture;
import fr.ign.cogit.geoxygene.appli.gl.Texture;
import fr.ign.cogit.geoxygene.appli.render.RenderingException;
import fr.ign.cogit.geoxygene.math.MathUtil;
import fr.ign.cogit.geoxygene.math.ui.GraphPanel;
import fr.ign.cogit.geoxygene.util.gl.GLTools;

/**
 * @author JeT
 * This renderer writes GL Code to perform GL rendering
 * It draws line using textures
 */
public class LinePrimitiveRenderer extends AbstractPrimitiveRenderer {

    private static Logger logger = Logger.getLogger(LinePrimitiveRenderer.class.getName());

    private static final double defaultLineWidth = 4.;
    private double lineWidth = defaultLineWidth;
    private Texture texture = null;

    /**
     * Constructor
     * @param backgroundColor
     * @param foregroundColor
     */
    public LinePrimitiveRenderer() {
        this(defaultLineWidth);
    }

    /**
     * Constructor
     * @param backgroundColor
     * @param foregroundColor
     */
    public LinePrimitiveRenderer(final double lineWidth) {
        super();
        this.lineWidth = lineWidth;
        TiledTexture tiledTexture = new TiledTexture("./src/main/resources/textures/cell02.png", 4, 256, 150, 210);
        tiledTexture.setTextureSizeInWorldCoordinates(400);
        this.texture = tiledTexture;
    }

    /**
     * @return the lineWidth
     */
    public double getLineWidth() {
        return this.lineWidth;
    }

    /**
     * @param lineWidth the lineWidth to set
     */
    public void setLineWidth(final double lineWidth) {
        this.lineWidth = lineWidth;
    }

    /* (non-Javadoc)
     * @see fr.ign.cogit.geoxygene.appli.render.PrimitiveRenderer#render()
     */
    @Override
    public void render() throws RenderingException {
        if (this.getViewport() == null) {
            throw new RenderingException("viewport is not set");
        }
        for (DrawingPrimitive primitive : this.getPrimitives()) {
            this.render(primitive, this.getViewport());
        }

    }

    /**
     * Render one drawing primitive
     * @param primitive
     * @throws RenderingException
     */
    private void render(final DrawingPrimitive primitive, final Viewport viewport) throws RenderingException {
        if (!primitive.isLeaf()) {
            MultiDrawingPrimitive multiPrimitive = (MultiDrawingPrimitive) primitive;
            for (DrawingPrimitive childPrimitive : multiPrimitive.getPrimitives()) {
                this.render(childPrimitive, viewport);
            }
            return;
        } else if (primitive instanceof ParameterizedPolyline) {
            this.renderLine((ParameterizedPolyline) primitive);
            return;
        }
        logger.warn(this.getClass().getSimpleName() + " do not know how to paint primitives "
                + primitive.getClass().getSimpleName());
    }

    /**
     * Render simple line.
     * @param primitive primitive to paint
     */
    private void renderLine(final ParameterizedPolyline line) {
        if (line.getPointCount() < 2) {
            logger.warn("Line has " + line.getPointCount() + " points and cannot be rendered");
            return;
        }
        this.texture.initializeRendering();
        this.texture.setRange(0., 0, line.getParameter(line.getPointCount() - 1), 1);
        //    System.err.println("set range to " + this.texture.getMinX() + "x" + this.texture.getMinY() + " - " + this.texture.getMaxX() + "x"
        //        + this.texture.getMaxY());
        /**
         * p1 is the nth point, n1 the segment normal at p1 point 
         * p2 is the (n+1)th point, n2 the segment normal at p2 point
         * 
         * pXa, pXb are the 
         */
        Point2d p1 = line.getPoint(0); // nth point
        double p1t = line.getParameter(0);
        Point2d p2 = line.getPoint(1); // n+1 th point
        double p2t = line.getParameter(1);
        Point2d p3 = null; // n+2 th point
        Vector2d v1 = MathUtil.vector(p1, p2); // line direction at p1
        Vector2d v2 = null; // line direction at p2 
        Vector2d n1 = MathUtil.computeNormal(v1); // line normal at p1 (perpendicular to segment direction)
        Vector2d n2 = null; // line normal at p2 (perpendicular to segment direction)
        Point2d p1a = MathUtil.pointOfLine(p1, n1, -this.getLineWidth() / 2); // first stretched point at p1 (p1 + lineWidth/2 * n1)
        Point2d p1b = MathUtil.pointOfLine(p1, n1, this.getLineWidth() / 2); // second stretched point at p1 (p1 - lineWidth/2 * n1)
        Point2d p2a = null; // first stretched point at p2 (p2 + lineWidth/2 * n2)
        Point2d p2b = null; // second stretched point at p2 (p2 - lineWidth/2 * n2)

        if (line.getPointCount() <= 2) {
            p3 = p2;
            n2 = n1;
        }

        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
        GL11.glBegin(GL11.GL_QUAD_STRIP);
        try {
            GL11.glTexCoord2d(p1t, 0);
            GLTools.glTexCoord(this.texture.vertexCoordinates(p1t, 0));
            GL11.glVertex2d(p1a.x, p1a.y);
            GLTools.glTexCoord(this.texture.vertexCoordinates(p1t, 1));
            GL11.glVertex2d(p1b.x, p1b.y);
            //      System.err.println("set first point coordinates = " + p1t + "x" + "0" + " => " + this.texture.vertexCoordinates(p1t, 0));
            //      System.err.println("set first point coordinates = " + p1t + "x" + "1" + " => " + this.texture.vertexCoordinates(p1t, 1));

            for (int nPoint = 0; nPoint < line.getPointCount() - 2; nPoint++) {

                p3 = line.getPoint(nPoint + 2);
                v2 = MathUtil.vector(p2, p3);
                n2 = MathUtil.computeNormal(v2);
                p2a = MathUtil.pointOfLine(p2, n2, -this.getLineWidth() / 2);
                p2b = MathUtil.pointOfLine(p2, n2, this.getLineWidth() / 2);
                p2t = line.getParameter(nPoint);

                Point2d Ia = MathUtil.intersectionPoint(p1a, v1, p2a, v2);
                Point2d Ib = MathUtil.intersectionPoint(p1b, v1, p2b, v2);
                if (Ia == null || Ib == null) {
                    Ia = MathUtil.mean(p1a, p2a);
                    Ib = MathUtil.mean(p1b, p2b);
                }

                GLTools.glTexCoord(this.texture.vertexCoordinates(p2t, 0));
                GL11.glVertex2d(Ia.x, Ia.y);
                GLTools.glTexCoord(this.texture.vertexCoordinates(p2t, 1));
                GL11.glVertex2d(Ib.x, Ib.y);

                //        System.err.println("set #" + nPoint + " point coordinates = " + p2t + "x" + "0" + " => " + this.texture.vertexCoordinates(p2t, 0));
                //        System.err.println("set #" + nPoint + " point coordinates = " + p2t + "x" + "1" + " => " + this.texture.vertexCoordinates(p2t, 1));
                // shift context to the next point
                p1 = p2;
                p1t = p2t;
                n1 = n2;
                v1 = v2;
                p1a = Ia;
                p1b = Ib;
                p2 = p3;

            }
            // draw the last point
            Point2d p3a = MathUtil.pointOfLine(p3, n2, -this.getLineWidth() / 2);
            Point2d p3b = MathUtil.pointOfLine(p3, n2, this.getLineWidth() / 2);
            double p3t = line.getParameter(line.getPointCount() - 1);
            GLTools.glTexCoord(this.texture.vertexCoordinates(p3t, 0));
            GL11.glVertex2d(p3a.x, p3a.y);
            GLTools.glTexCoord(this.texture.vertexCoordinates(p3t, 1));
            GL11.glVertex2d(p3b.x, p3b.y);
            //      System.err.println("set last point coordinates = " + p3t + "x" + "0" + " => " + this.texture.vertexCoordinates(p3t, 0));
            //      System.err.println("set last point coordinates = " + p3t + "x" + "1" + " => " + this.texture.vertexCoordinates(p3t, 1));
        } finally {
            GL11.glEnd();
        }

        this.texture.initializeRendering();

    }

    static boolean first = true; // debug purpose only

    /**
     * Render simple line.
     * @param primitive primitive to paint
     */
    private void renderLineDebug(final ParameterizedPolyline line) {
        if (line.getPointCount() < 2) {
            logger.warn("Line has " + line.getPointCount() + " points and cannot be rendered");
            return;
        }
        final double epsilon = 1E-1;
        /**
         * p1 is the nth point, n1 the segment normal at p1 point 
         * p2 is the (n+1)th point, n2 the segment normal at p2 point
         * 
         * pXa, pXb are the 
         */
        Point2d p1 = line.getPoint(0); // nth point
        Point2d p2 = line.getPoint(1); // n+1 th point
        Point2d p3 = null; // n+2 th point
        Vector2d v1 = MathUtil.vector(p1, p2); // line direction at p1
        Vector2d v2 = null; // line direction at p2 
        Vector2d n1 = MathUtil.computeNormal(v1); // line normal at p1 (perpendicular to segment direction)
        Vector2d n2 = null; // line normal at p2 (perpendicular to segment direction)
        Point2d p1a = MathUtil.pointOfLine(p1, n1, -this.getLineWidth() / 2); // first stretched point at p1 (p1 + lineWidth/2 * n1)
        Point2d p1b = MathUtil.pointOfLine(p1, n1, this.getLineWidth() / 2); // second stretched point at p1 (p1 - lineWidth/2 * n1)
        Point2d p2a = null; // first stretched point at p2 (p2 + lineWidth/2 * n2)
        Point2d p2b = null; // second stretched point at p2 (p2 - lineWidth/2 * n2)

        if (line.getPointCount() <= 2) {
            p3 = p2;
            n2 = n1;
        }

        double s = 1;
        GL11.glLineWidth(2.f);
        GL11.glBegin(GL11.GL_LINES);
        // first point
        GL11.glColor3d(1, 0, 0);
        GL11.glVertex2d(p1a.x, p1a.y);
        GL11.glVertex2d(p1b.x, p1b.y);
        try {

            for (int nPoint = 0; nPoint < line.getPointCount() - 2; nPoint++) {

                p3 = line.getPoint(nPoint + 2);
                v2 = MathUtil.vector(p2, p3);
                n2 = MathUtil.computeNormal(v2);
                p2a = MathUtil.pointOfLine(p2, n2, -this.getLineWidth() / 2);
                p2b = MathUtil.pointOfLine(p2, n2, this.getLineWidth() / 2);

                GL11.glColor3d(.5, .5, .5);
                GL11.glVertex2d(p1a.x, p1a.y);
                GL11.glVertex2d(p1b.x, p1b.y);

                /*        GL11.glColor3d(.5, .5, .5);
                        GL11.glVertex2d(p1.x, p1.y);
                        GL11.glVertex2d(p1.x + s * v1.x, p1.y + s * v1.y);
                    
                        GL11.glColor3d(.5, .5, .5);
                        GL11.glVertex2d(p1.x, p1.y);
                        GL11.glVertex2d(p1.x + s * n1.x, p1.y + s * n1.y);
                */
                Point2d Ia = MathUtil.intersectionPoint(p1a, v1, p2a, v2, epsilon);
                Point2d Ib = MathUtil.intersectionPoint(p1b, v1, p2b, v2, epsilon);

                // debug
                if (first && Ia != null && Ib != null && MathUtil.norm(MathUtil.vector(Ia, Ib)) > 100) {
                    first = false;
                    JDialog dialog = new JDialog();
                    GraphPanel graphPanel = new GraphPanel();
                    dialog.getContentPane().add(graphPanel);
                    dialog.pack();
                    dialog.setVisible(true);

                    graphPanel.addPoint("p1", p1);
                    graphPanel.addPoint("p2", p2);
                    graphPanel.addPoint("p3", p3);

                    //          graphPanel.addVector("n1", p1, n1);
                    //          graphPanel.addVector("n2", p2, n2);
                    graphPanel.addVector("v1", p1, v1);
                    graphPanel.addVector("v2", p1, v2);
                    graphPanel.addVector(".", p1a, v1);
                    graphPanel.addVector(",", p1b, v1);
                    graphPanel.addVector("`", p2a, v2);
                    graphPanel.addVector("'", p2b, v2);
                    graphPanel.addPoint("p1a", p1a);
                    graphPanel.addPoint("p1b", p1b);
                    graphPanel.addPoint("p2a", p2a);
                    graphPanel.addPoint("p2b", p2b);

                    System.out.println("v1.v2 = " + MathUtil.cross(v1, v2));
                    //          graphPanel.addPoint("Ia", Ia);
                    //          graphPanel.addPoint("Ib", Ib);

                    System.out.println(nPoint + " on " + line.getPointCount() + " =>");
                    System.out.println(" p1   = " + p1);
                    System.out.println(" p2   = " + p2);
                    System.out.println(" p3   = " + p3);
                    System.out.println(" n1   = " + n1);
                    System.out.println(" n2   = " + n2);
                    System.out.println(" v1   = " + v1);
                    System.out.println(" v2   = " + v2);
                    System.out.println(" p1a  = " + p1a);
                    System.out.println(" p1b  = " + p1b);
                    System.out.println(" p2a  = " + p2a);
                    System.out.println(" p2b  = " + p2b);
                    System.out.println(" Ia   = " + Ia);
                    System.out.println(" Ib   = " + Ib);
                    p3 = line.getPoint(nPoint + 2);
                    v2 = MathUtil.vector(p2, p3);
                    n2 = MathUtil.computeNormal(v2);
                    p2a = MathUtil.pointOfLine(p2, n2, -this.getLineWidth() / 2);
                    p2b = MathUtil.pointOfLine(p2, n2, this.getLineWidth() / 2);
                    Ia = MathUtil.intersectionPoint(p1a, v1, p2a, v2, epsilon);
                    Ib = MathUtil.intersectionPoint(p1b, v1, p2b, v2, epsilon);

                }
                if (Ia == null || Ib == null) {
                    Ia = MathUtil.mean(p1a, p2a);
                    Ib = MathUtil.mean(p1b, p2b);
                }
                // if no intersection, use p2a & p2b
                if (Ia == null) {
                    GL11.glColor3d(.5, .5, .5);
                    GL11.glVertex2d(p2a.x, p2b.y);
                } else {
                    GL11.glColor3d(0, 0, 1);
                    GL11.glVertex2d(Ia.x, Ia.y);
                }
                if (Ib == null) {
                    GL11.glColor3d(.5, .5, .5);
                    GL11.glVertex2d(p2b.x, p2b.y);
                } else {
                    GL11.glColor3d(0, 1, 0);
                    GL11.glVertex2d(Ib.x, Ib.y);
                }
                // shift context to the next point
                p1 = p2;
                n1 = n2;
                v1 = v2;
                p1a = p2a;
                p1b = p2b;
                p2 = p3;

            }
            if (p3 == null || n2 == null) {
                System.err.println("p3 = " + p3 + " n2 = " + n2 + " nbpt = " + line.getPointCount());
            }
            // draw the last point
            Point2d p3a = MathUtil.pointOfLine(p3, n2, -this.getLineWidth() / 2);
            Point2d p3b = MathUtil.pointOfLine(p3, n2, this.getLineWidth() / 2);
            GL11.glColor3d(1, 1, 0);
            GL11.glVertex2d(p3a.x, p3a.y);
            GL11.glVertex2d(p3b.x, p3b.y);
        } finally {
            GL11.glEnd();
        }
    }

    @Override
    public void initializeRendering() throws RenderingException {
        // nothing to initialize

    }

    @Override
    public void finalizeRendering() throws RenderingException {
        // nothing to finalize
    }

}