Package org.kabeja.dxf

Source Code of org.kabeja.dxf.DXFPolyline

/*
* Created on Jun 29, 2004
*
*/
package org.kabeja.dxf;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.kabeja.dxf.helpers.Point;
import org.kabeja.dxf.helpers.Vector;
import org.kabeja.math.MathUtils;


/**
* @author <a href="mailto:simon.mieth@gmx.de>Simon Mieth </a>
*
*/
public class DXFPolyline extends DXFEntity {
    protected static final double QUARTER_CIRCLE_ANGLE = Math.tan(0.39269908169872414D);
    protected ArrayList<DXFVertex> vertices = new ArrayList<DXFVertex>();
    protected double startWidth = 0.0;
    protected double endWidth = 0.0;
    protected boolean constantWidth = true;
    protected int surefaceType = 0;
    protected int surefaceDensityRows = 0;
    protected int surefaceDensityColumns = 0;
    protected int rows = 0;
    protected int columns = 0;

    /**
     *
     */
    public DXFPolyline() {
    }

    /*
     * (non-Javadoc)
     *
     * @see org.dxf2svg.dxf.DXFEntity#updateViewPort()
     */
    public Bounds getBounds() {
        Bounds bounds = new Bounds();

        Iterator<DXFVertex> i = vertices.iterator();

        if (i.hasNext()) {
            DXFVertex last;
            DXFVertex first;
            DXFVertex v = null;

            last = first = (DXFVertex) i.next();
            bounds.addToBounds(last.getPoint());

            while (i.hasNext()) {
                v = (DXFVertex) i.next();
                addToBounds(last, v, bounds);
                last = v;
            }

            if ((v != null) && (v.getBulge() != 0.0)) {
                addToBounds(v, first, bounds);
            }
        } else {
            bounds.setValid(false);
        }

        return bounds;
    }

    public void addVertex(DXFVertex vertex) {
        vertices.add(vertex);

        if (!vertex.isConstantWidth()) {
            constantWidth = false;
        }
    }

    public int getVertexCount() {
        return this.vertices.size();
    }

    public Iterator<DXFVertex> getVertexIterator() {
        return this.vertices.iterator();
    }

    public void removeVertex(DXFVertex vertex) {
        // remove and check the constantwidth
        constantWidth = true;

        Iterator<DXFVertex> i = vertices.iterator();

        while (i.hasNext()) {
            DXFVertex v = i.next();

            if (v == vertex) {
                i.remove();
            } else if (!v.isConstantWidth()) {
                constantWidth = false;
            }
        }
    }

    public void removeVertex(int index) {
        constantWidth = true;

        for (int i = 0; i < vertices.size(); i++) {
            DXFVertex v = (DXFVertex) vertices.get(i);

            if (index == i) {
                vertices.remove(i);
            } else if (!v.isConstantWidth()) {
                constantWidth = false;
            }
        }
    }

    public DXFVertex getVertex(int i) {
        return (DXFVertex) vertices.get(i);
    }

    /**
     * Returns the distance between 2 DXFPoints
     *
     * @param start
     * @param end
     * @return the length between the two points
     */
    protected double getLength(DXFPoint start, DXFPoint end) {
        double value = Math.sqrt(Math.pow(end.getX() - start.getX(), 2) +
                Math.pow(end.getY() - start.getY(), 2));

        return value;
    }

    /**
     * Caculate the radius of a cut circle segment between 2 DXFVertex
     *
     * @param bulge
     *            the vertex bulge
     * @param length
     *            the length of the circle cut
     */
    public double getRadius(double bulge, double length) {
        double h = (bulge * length) / 2;
        double value = (h / 2) + (Math.pow(length, 2) / (8 * h));

        return Math.abs(value);
    }

    /*
     * (non-Javadoc)
     *
     * @see de.miethxml.kabeja.dxf.DXFEntity#getType()
     */
    public String getType() {
        return DXFConstants.ENTITY_TYPE_POLYLINE;
    }

    /**
     * @return Returns the endWidth.
     */
    public double getEndWidth() {
        return endWidth;
    }

    /**
     * @param endWidth
     *            The endWidth to set.
     */
    public void setEndWidth(double endWidth) {
        this.endWidth = endWidth;
    }

    /**
     * @return Returns the startWidth.
     */
    public double getStartWidth() {
        return startWidth;
    }

    /**
     * @param startWidth
     *            The startWidth to set.
     */
    public void setStartWidth(double startWidth) {
        this.startWidth = startWidth;
    }

    public boolean isClosed() {
        // the closed Flag
        return (this.flags & 1) == 1;
    }

    public boolean isCurveFitVerticesAdded() {
        return (this.flags & 2) == 2;
    }

    public boolean isSplineFitVerticesAdded() {
        return (this.flags & 4) == 4;
    }

    public boolean is3DPolygon() {
        return (this.flags & 8) == 8;
    }

    public boolean is3DPolygonMesh() {
        return (this.flags & 16) == 16;
    }

    public boolean isPolyfaceMesh() {
        return (this.flags & 64) == 64;
    }

    public boolean isClosedMeshNDirection() {
        return (this.flags & 32) == 32;
    }

    public boolean isClosedMeshMDirection() {
        return (this.flags & 1) == 1;
    }

    public boolean isQuadSpline() {
        if (isSplineFitVerticesAdded()) {
            return this.surefaceType == 5;
        }

        return false;
    }

    public boolean isCubicSpline() {
        if (isSplineFitVerticesAdded()) {
            return this.surefaceType == 6;
        }

        return false;
    }

    public boolean isConstantWidth() {
        //TODO review to see if the property is always set correct
        if (!this.constantWidth) {
            return false;
        } else {
            this.constantWidth = true;

            Iterator<DXFVertex> i = vertices.iterator();

            while (i.hasNext()) {
                DXFVertex vertex = (DXFVertex) i.next();

                if (!vertex.isConstantWidth()) {
                    this.constantWidth = false;

                    return this.constantWidth;
                }
            }
        }

        return this.constantWidth;
    }

    /**
     * @return Returns the surefaceType.
     */
    public int getSurefaceType() {
        return surefaceType;
    }

    /**
     * @param surefaceType
     *            The surefaceType to set.
     */
    public void setSurefaceType(int surefaceType) {
        this.surefaceType = surefaceType;
    }

    /**
     * @return Returns the columns.
     */
    public int getSurefaceDensityColumns() {
        return surefaceDensityColumns;
    }

    /**
     * @param columns
     *            The columns to set.
     */
    public void setSurefaceDensityColumns(int columns) {
        this.surefaceDensityColumns = columns;
    }

    /**
     * @return Returns the rows.
     */
    public int getSurefaceDensityRows() {
        return surefaceDensityRows;
    }

    /**
     * @param rows
     *            The rows to set.
     */
    public void setSurefaceDensityRows(int rows) {
        this.surefaceDensityRows = rows;
    }

    protected void addToBounds(DXFVertex start, DXFVertex end, Bounds bounds) {
        if (start.getBulge() != 0) {
            // calculte the height
            double l = MathUtils.distance(start.getPoint(), end.getPoint());

            // double h = Math.abs(last.getBulge()) * l / 2;
            double r = this.getRadius(start.getBulge(), l);

            double s = l / 2;
            Vector edgeDirection = MathUtils.getVector(start.getPoint(),
                    end.getPoint());
            edgeDirection = MathUtils.normalize(edgeDirection);

            Point centerPoint = MathUtils.getPointOfStraightLine(start.getPoint(),
                    edgeDirection, s);

            Vector centerPointDirection = MathUtils.crossProduct(edgeDirection,
                    this.getExtrusion().getNormal());
            centerPointDirection = MathUtils.normalize(centerPointDirection);

            // double t = Math.sqrt(Math.pow(r, 2) - Math.pow(s, 2));
            // double t = 0;
            double h = Math.abs(start.getBulge() * l) / 2;

            // if(Math.abs(start.getBulge())>=1.0){
            // t = h-r;
            // }else{
            // //t = Math.sqrt(Math.pow(r, 2) - Math.pow(s, 2));
            // t=r-h;
            // }
            // the center point of the arc
            int startQ = 0;
            int endQ = 0;

            double bulge = start.getBulge();

            if (bulge > 0) {
                // the arc goes over the right side, but where is the center
                // point?
                if (bulge > 1.0) {
                    double t = h - r;
                    centerPoint = MathUtils.getPointOfStraightLine(centerPoint,
                            centerPointDirection, t);
                } else {
                    double t = r - h;
                    centerPoint = MathUtils.getPointOfStraightLine(centerPoint,
                            centerPointDirection, (-1 * t));
                }

                endQ = MathUtils.getQuadrant(end.getPoint(), centerPoint);
                startQ = MathUtils.getQuadrant(start.getPoint(), centerPoint);
            } else {
                // the arc goes over the left side, but where is the center
                // point?
                if (bulge < -1.0) {
                    double t = h - r;
                    centerPoint = MathUtils.getPointOfStraightLine(centerPoint,
                            centerPointDirection, (-1 * t));
                } else {
                    double t = r - h;
                    centerPoint = MathUtils.getPointOfStraightLine(centerPoint,
                            centerPointDirection, t);
                }

                startQ = MathUtils.getQuadrant(end.getPoint(), centerPoint);
                endQ = MathUtils.getQuadrant(start.getPoint(), centerPoint);
            }

            if (endQ < startQ) {
                endQ += 4;
            } else if ((endQ == startQ) &&
                    (Math.abs(start.getBulge()) > QUARTER_CIRCLE_ANGLE)) {
                endQ += 4;
            }

            while (endQ > startQ) {
                switch (startQ) {
                case 0:
                    bounds.addToBounds(centerPoint.getX(),
                        centerPoint.getY() + r, centerPoint.getZ());

                    break;

                case 1:
                    bounds.addToBounds(centerPoint.getX() - r,
                        centerPoint.getY(), centerPoint.getZ());

                    break;

                case 2:
                    bounds.addToBounds(centerPoint.getX(),
                        centerPoint.getY() - r, centerPoint.getZ());

                    break;

                case 3:
                    bounds.addToBounds(centerPoint.getX() + r,
                        centerPoint.getY(), centerPoint.getZ());
                    endQ -= 4;
                    startQ -= 4;

                    break;
                }

                startQ++;
            }
        }

        bounds.addToBounds(start.getPoint());
        bounds.addToBounds(end.getPoint());
    }

    public DXFVertex getPolyFaceMeshVertex(int index) {
        Iterator<DXFVertex> i = this.vertices.iterator();
        int count = 1;

        while (i.hasNext()) {
            DXFVertex v = (DXFVertex) i.next();

            if (v.isPolyFaceMeshVertex()) {
                if (count == index) {
                    return v;
                } else {
                    count++;
                }
            }
        }

        return null;
    }

    /**
     * @return Returns the column.
     */
    public int getColumns() {
        return columns;
    }

    /**
     * @param column
     *            The column to set.
     */
    public void setColumns(int column) {
        this.columns = column;
    }

    /**
     * @return Returns the rows.
     */
    public int getRows() {
        return rows;
    }

    /**
     * @param rows
     *            The rows to set.
     */
    public void setRows(int rows) {
        this.rows = rows;
    }

    public boolean isSimpleMesh() {
        return (this.surefaceType == 0) && ((this.flags & 4) == 0);
    }

    public boolean isQuadSurefaceMesh() {
        return (this.surefaceType == 5) && ((this.flags & 4) == 4);
    }

    public boolean isCubicSurefaceMesh() {
        return (this.surefaceType == 6) && ((this.flags & 4) == 4);
    }

    public boolean isBezierSurefaceMesh() {
        return (this.surefaceType == 8) && ((this.flags & 4) == 4);
    }

    public double getLength() {
        double length = 0.0;

        if (isCubicSpline() || isQuadSpline()) {
            return getSplineApproximationLength();
        } else if (isPolyfaceMesh()) {
            return getPolyfaceLength();
        } else if (is3DPolygonMesh() || isBezierSurefaceMesh() ||
                isCubicSurefaceMesh()) {
            return getMeshLength();
        } else {
            // a normal polyline with or without bulges
            Iterator<DXFVertex> i = this.vertices.iterator();
            DXFVertex first;
            DXFVertex last = first = (DXFVertex) i.next();

            while (i.hasNext()) {
                DXFVertex v = (DXFVertex) i.next();
                length += this.getSegmentLength(last, v);
                last = v;
            }

            if (this.isClosed()) {
                length += this.getSegmentLength(last, first);
            }
        }

        return length;
    }

    protected double getSegmentLength(DXFVertex start, DXFVertex end) {
        double l = MathUtils.distance(start.getPoint(), end.getPoint());

        if (start.getBulge() == 0.0) {
            return l;
        } else {
            double alpha = 4 * Math.atan(Math.abs(start.getBulge()));

            double r = l / (2 * Math.sin(alpha / 2));
            double d = (Math.PI * Math.toDegrees(alpha) * r) / 180;

            return d;
        }
    }

    protected double getSplineApproximationLength() {
        double length = 0.0;

        // use the approximation
        Iterator<DXFVertex> i = this.vertices.iterator();
        DXFVertex first;
        DXFVertex last = first = null;

        while (i.hasNext()) {
            DXFVertex v = (DXFVertex) i.next();

            if (v.is2DSplineApproximationVertex()) {
                if (first == null) {
                    first = last = v;
                } else {
                    length += getSegmentLength(last, v);
                    last = v;
                }
            }
        }

        if (this.isClosed()) {
            length += getSegmentLength(last, first);
        }

        return length;
    }

    protected double getPolyfaceLength() {
        double length = 0.0;
        Iterator<DXFVertex> i = this.vertices.iterator();

        while (i.hasNext()) {
            DXFVertex v = (DXFVertex) i.next();

            if (v.isFaceRecord()) {
                DXFVertex v1 = getPolyFaceMeshVertex(v.getPolyFaceMeshVertex0());
                DXFVertex v2 = getPolyFaceMeshVertex(v.getPolyFaceMeshVertex1());
                DXFVertex v3 = getPolyFaceMeshVertex(v.getPolyFaceMeshVertex2());
                DXFVertex v4 = getPolyFaceMeshVertex(v.getPolyFaceMeshVertex3());

                if (v.isPolyFaceEdge0Visible() &&
                        (v.getPolyFaceMeshVertex0() != 0)) {
                    length += getSegmentLength(v1, v2);
                }

                if (v.isPolyFaceEdge1Visible() &&
                        (v.getPolyFaceMeshVertex1() != 0)) {
                    length += getSegmentLength(v2, v3);
                }

                if (v.isPolyFaceEdge2Visible() &&
                        (v.getPolyFaceMeshVertex2() != 0)) {
                    length += getSegmentLength(v3, v4);
                }

                if (v.isPolyFaceEdge3Visible() &&
                        (v.getPolyFaceMeshVertex3() != 0)) {
                    length += getSegmentLength(v4, v1);
                } else if ((v4 == null) && (v3 != null)) {
                    // triangle
                    length += getSegmentLength(v3, v1);
                }
            }
        }

        return length;
    }

    protected double getMeshLength() {
        double length = 0.0;

        if (isSimpleMesh()) {
            DXFVertex[][] points = new DXFVertex[this.rows][this.columns];
            Iterator<DXFVertex> it = this.vertices.iterator();

            // create a line for each row
            for (int i = 0; i < this.rows; i++) {
                for (int x = 0; x < this.columns; x++) {
                    DXFVertex v = (DXFVertex) it.next();
                    points[i][x] = v;

                    if (x > 0) {
                        length += getSegmentLength(points[i][x - 1],
                            points[i][x]);
                    }
                }

                if (isClosedMeshNDirection()) {
                    length += getSegmentLength(points[i][points[i].length - 1],
                        points[i][0]);
                }
            }

            // create a line for each column
            for (int i = 0; i < this.columns; i++) {
                for (int x = 0; x < this.rows; x++) {
                    if (x > 0) {
                        length += getSegmentLength(points[x - 1][i],
                            points[x][i]);
                    }
                }

                if (isClosedMeshMDirection()) {
                    length += getSegmentLength(points[points[i].length - 1][i],
                        points[0][i]);
                }
            }
        } else {
            DXFVertex[][] points = new DXFVertex[this.surefaceDensityRows][this.surefaceDensityColumns];
            Iterator<DXFVertex> vi = this.vertices.iterator();
            List<DXFVertex> appVertices = new ArrayList<DXFVertex>();

            while (vi.hasNext()) {
                DXFVertex v = (DXFVertex) vi.next();

                if (v.isMeshApproximationVertex()) {
                    appVertices.add(v);
                }
            }

            Iterator<DXFVertex> it = appVertices.iterator();

            // create a line for each row
            for (int i = 0; i < this.surefaceDensityRows; i++) {
                for (int x = 0; x < this.surefaceDensityColumns; x++) {
                    DXFVertex v = (DXFVertex) it.next();
                    points[i][x] = v;

                    if (x > 0) {
                        length += getSegmentLength(points[i][x - 1],
                            points[i][x]);
                    }
                }

                if (isClosedMeshNDirection()) {
                    length += getSegmentLength(points[i][points[i].length - 1],
                        points[i][0]);
                }
            }

            // create a line for each column
            for (int i = 0; i < this.surefaceDensityColumns; i++) {
                for (int x = 0; x < this.surefaceDensityRows; x++) {
                    if (x > 0) {
                        length += getSegmentLength(points[x - 1][i],
                            points[x][i]);
                    }
                }

                if (isClosedMeshMDirection()) {
                    length += getSegmentLength(points[points[i].length - 1][i],
                        points[0][i]);
                }
            }
        }

        return length;
    }
}
TOP

Related Classes of org.kabeja.dxf.DXFPolyline

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.