<commit_before>/*
 * This file is part of Mapyrus, software for plotting maps.
 * Copyright (C) 2003, 2004 <NAME>.
 *
 * Mapyrus 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 of the License, or
 * (at your option) any later version.
 *
 * Mapyrus 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 Mapyrus; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/*
 * @(#) $Id$
 */
package org.mapyrus;

import java.awt.geom.*;
import java.util.ArrayList;

import org.mapyrus.geom.LineEquation;

/**
 * A geometric path.  A series of coordinates, either separate or joined together
 * as part of a line or polygon.  Coordinate pairs are joined with either
 * straight lines, arcs or bezier curves.
 */
public class GeometricPath
{
	/*
	 * What to calculate when walking through path?
	 */
	static final int CALCULATE_LENGTHS = 1;
	static final int CALCULATE_AREAS = 2;
	static final int CALCULATE_CENTROID = 3;
	static final int CALCULATE_PIP = 4;	/* point in polygon */

	/*
	 * An identity matrix results in no transformation.
	 */
	static AffineTransform mIdentityMatrix = new AffineTransform();

	/*
	 * Coordinates of path.
	 */
	private GeneralPath mPath;
	
	/*
	 * Coordinates and rotation angle at each moveTo point.  GeneralPath
	 * ignores successive moveTo points so we _must_ save them ourselves.
	 */
	private ArrayList mRotations;
	private ArrayList mMoveTos;

	/*
	 * Count of number of lineTos in path.
	 */
	private int mNLineTos;

	/**
	 * Create new, empty geometric path.
	 */
	public GeometricPath()
	{
		mPath = new GeneralPath();
		mRotations = new ArrayList();
		mMoveTos = new ArrayList();
		mNLineTos = 0;
	}

	/**
	 * Construct path as a copy of an existing path.
	 * @param path is existing path to copy.
	 */
	public GeometricPath(GeometricPath path)
	{
		mPath = (GeneralPath)(path.mPath.clone());	
		mNLineTos = path.mNLineTos;

		/*
		 * Copy the list of moveTo points and rotations.
		 */
		mMoveTos = (ArrayList)(path.mMoveTos.clone());
		mRotations = (ArrayList)(path.mRotations.clone());
	}

	/**
	 * Add point to path.
	 * @param x X coordinate to move to
	 * @param y Y coordinate to move to
	 * @param rotation angle to use for a symbol at this point.
	 */
	public void moveTo(float x, float y, double rotation)
	{
		mPath.moveTo(x, y);
		mMoveTos.add(new Point2D.Float(x, y));
		mRotations.add(new Double(rotation));
	}

	/**
	 * Add point to path with straight line segment from last point.
	 * @param coords two element array containing x and y coordinates of point.
	 */	
	public void lineTo(float x, float y)
	{
		mPath.lineTo(x, y);
		mNLineTos++;
	}

	/**
	 * Add circular arc to path from last point to a new point, given centre and direction.
	 * @param direction positive for clockwise, negative for anti-clockwise.
	 * @param xCentre X coordinate of centre point of arc.
	 * @param yCentre Y coordinate of centre point of arc.
	 * @param xEnd X coordinate of end point of arc.
	 * @param yEnd Y coordinate of end point of arc.
	 */
	public void arcTo(int direction, float xCentre, float yCentre,
		float xEnd, float yEnd) throws MapyrusException
	{
		double radius;
		Point2D lastPt = mPath.getCurrentPoint();
		if (lastPt == null)
			throw new MapyrusException(MapyrusMessages.get(MapyrusMessages.NO_ARC_START));

		float lastX = (float)(lastPt.getX());
		float lastY = (float)(lastPt.getY());
	
		/*
		 * If arc end point is very close to arc start point then make them
		 * the same point to force a full circle.  New arc coordinates are passed
		 * as double precision numbers but coordinates already in path are only
		 * stored with floating precision so some round-off can occur.
		 */
		if (NumericalAnalysis.equals(lastX, xEnd) &&
			NumericalAnalysis.equals(lastY, yEnd))
		{
			xEnd = lastX;
			yEnd = lastY;
		}

		radius = Point2D.distance(xCentre, yCentre, xEnd, yEnd);

		Arc2D.Float arc = new Arc2D.Float();
		arc.setArcByCenter(xCentre, yCentre, radius, 0.0, 1.0, Arc2D.OPEN);
		arc.setAngles(lastX, lastY, xEnd, yEnd);
		if (direction < 0.0)
		{
			/*
			 * Force arc to go anti-clockwise.
			 */
			arc.setAngleExtent(arc.getAngleExtent() - 360.0);
		}
	
		mPath.append(arc, true);
		mNLineTos++;
	}

	/**
	 * Closes path back to the last point created with moveTo method.
	 */
	public void closePath()
	{
		mPath.closePath();
		mNLineTos++;
	}<commit_msg>Add ellipseTo() to add ellipse to path.<commit_after>/*
 * This file is part of Mapyrus, software for plotting maps.
 * Copyright (C) 2003, 2004 <NAME>.
 *
 * Mapyrus 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 of the License, or
 * (at your option) any later version.
 *
 * Mapyrus 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 Mapyrus; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/*
 * @(#) $Id$
 */
package org.mapyrus;

import java.awt.geom.*;
import java.util.ArrayList;
import java.awt.geom.Ellipse2D;

import org.mapyrus.geom.LineEquation;

/**
 * A geometric path.  A series of coordinates, either separate or joined together
 * as part of a line or polygon.  Coordinate pairs are joined with either
 * straight lines, arcs or bezier curves.
 */
public class GeometricPath
{
	/*
	 * What to calculate when walking through path?
	 */
	static final int CALCULATE_LENGTHS = 1;
	static final int CALCULATE_AREAS = 2;
	static final int CALCULATE_CENTROID = 3;
	static final int CALCULATE_PIP = 4;	/* point in polygon */

	/*
	 * An identity matrix results in no transformation.
	 */
	static AffineTransform mIdentityMatrix = new AffineTransform();

	/*
	 * Coordinates of path.
	 */
	private GeneralPath mPath;
	
	/*
	 * Coordinates and rotation angle at each moveTo point.  GeneralPath
	 * ignores successive moveTo points so we _must_ save them ourselves.
	 */
	private ArrayList mRotations;
	private ArrayList mMoveTos;

	/*
	 * Count of number of lineTos in path.
	 */
	private int mNLineTos;

	/**
	 * Create new, empty geometric path.
	 */
	public GeometricPath()
	{
		mPath = new GeneralPath();
		mRotations = new ArrayList();
		mMoveTos = new ArrayList();
		mNLineTos = 0;
	}

	/**
	 * Construct path as a copy of an existing path.
	 * @param path is existing path to copy.
	 */
	public GeometricPath(GeometricPath path)
	{
		mPath = (GeneralPath)(path.mPath.clone());	
		mNLineTos = path.mNLineTos;

		/*
		 * Copy the list of moveTo points and rotations.
		 */
		mMoveTos = (ArrayList)(path.mMoveTos.clone());
		mRotations = (ArrayList)(path.mRotations.clone());
	}

	/**
	 * Add point to path.
	 * @param x X coordinate to move to
	 * @param y Y coordinate to move to
	 * @param rotation angle to use for a symbol at this point.
	 */
	public void moveTo(float x, float y, double rotation)
	{
		mPath.moveTo(x, y);
		mMoveTos.add(new Point2D.Float(x, y));
		mRotations.add(new Double(rotation));
	}

	/**
	 * Add point to path with straight line segment from last point.
	 * @param coords two element array containing x and y coordinates of point.
	 */	
	public void lineTo(float x, float y)
	{
		mPath.lineTo(x, y);
		mNLineTos++;
	}

	/**
	 * Add circular arc to path from last point to a new point, given centre and direction.
	 * @param direction positive for clockwise, negative for anti-clockwise.
	 * @param xCentre X coordinate of centre point of arc.
	 * @param yCentre Y coordinate of centre point of arc.
	 * @param xEnd X coordinate of end point of arc.
	 * @param yEnd Y coordinate of end point of arc.
	 */
	public void arcTo(int direction, float xCentre, float yCentre,
		float xEnd, float yEnd) throws MapyrusException
	{
		double radius;
		Point2D lastPt = mPath.getCurrentPoint();
		if (lastPt == null)
			throw new MapyrusException(MapyrusMessages.get(MapyrusMessages.NO_ARC_START));

		float lastX = (float)(lastPt.getX());
		float lastY = (float)(lastPt.getY());
	
		/*
		 * If arc end point is very close to arc start point then make them
		 * the same point to force a full circle.  New arc coordinates are passed
		 * as double precision numbers but coordinates already in path are only
		 * stored with floating precision so some round-off can occur.
		 */
		if (NumericalAnalysis.equals(lastX, xEnd) &&
			NumericalAnalysis.equals(lastY, yEnd))
		{
			xEnd = lastX;
			yEnd = lastY;
		}

		radius = Point2D.distance(xCentre, yCentre, xEnd, yEnd);

		Arc2D.Float arc = new Arc2D.Float();
		arc.setArcByCenter(xCentre, yCentre, radius, 0.0, 1.0, Arc2D.OPEN);
		arc.setAngles(lastX, lastY, xEnd, yEnd);
		if (direction < 0.0)
		{
			/*
			 * Force arc to go anti-clockwise.
			 */
			arc.setAngleExtent(arc.getAngleExtent() - 360.0);
		}
	
		mPath.append(arc, true);
		mNLineTos++;
	}

	/**
	 * Add ellipse to path.
	 * @param xMin minimum X coordinate of ellipse.
	 * @param yMin minimum Y coordinate of ellipse.
	 * @param xMax maximum X coordinate of ellipse.
	 * @param yMax maximum Y coordinate of ellipse.
	 */
	public void ellipseTo(double xMin, double yMin, double xMax, double yMax)
	{
		Point2D pt;
		pt = new Point2D.Float((float)xMax, (float)((yMin + yMax) / 2));
		mMoveTos.add(pt);

		/*
		 * Create elliptical shape and add it to path.
		 */
		Ellipse2D.Double ellipse = new Ellipse2D.Double(xMin, yMin,
			xMax - xMin, yMax - yMin);

		mPath.append(ellipse, false);
		mNLineTos++;
	}

	/**
	 * Closes path back to the last point created with moveTo method.
	 */
	public void closePath()
	{
		mPath.closePath();
		mNLineTos++;
	}
{'fraction_non_alphanumeric': 0.09738301391185913, 'fraction_numerical': 0.009144858449265493, 'mean_word_length': 3.3781942078364566, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1766874', 'n_tokens_mistral': 3576, 'n_tokens_neox': 3196, 'n_words': 1237}