Skip to content

Commit

Permalink
Merge pull request #179 from Divyeshhhh/improvepolygon
Browse files Browse the repository at this point in the history
improve regular polygon drawing algorithm
  • Loading branch information
creme332 authored Jul 31, 2024
2 parents e36ebc5 + e232d5d commit b872710
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,54 +17,65 @@ public class DrawRegularPolygon extends AbstractDrawer {

PolygonCalculator calculator = new PolygonCalculator();
private int numSides = 5; // default to 5 sides (pentagon)
private Point2D firstVertex = null;
private Point2D secondVertex = null;

public DrawRegularPolygon(AppState app, Canvas canvas) {
super(app, canvas);
}

@Override
protected void handleMouseMoved(Point2D polySpaceMousePosition) {
if (preview != null) {
// calculate side length of polygon
Point2D center = preview.getPlottedPoints().get(0);
int sideLength = (int) Math.abs(center.distance(polySpaceMousePosition));

int[][] res = calculator.getOrderedPoints(numSides, sideLength, (int) center.getX(), (int) center.getY());
Polygon p = new Polygon(res[0], res[1], res[0].length);
preview.setShape(p);
canvas.repaint();
}
// do nothing
}

@Override
protected void handleMousePressed(Point2D polySpaceMousePosition) {
if (preview == null) {
// center of polygon has been input
if (firstVertex == null) {
// user entered first vertex of polygon
firstVertex = polySpaceMousePosition;

// initialize shape preview
preview = new ShapeWrapper(canvasModel.getShapeColor(),
canvasModel.getLineType(),
canvasModel.getLineThickness());

// save first plotted point
preview.getPlottedPoints().add(polySpaceMousePosition);

// save preview
// update preview on canvas
canvasModel.getShapeManager().setShapePreview(preview);
return;
}

if (secondVertex == null) {
// user entered second vertex of polygon
secondVertex = polySpaceMousePosition;

// save second plotted point
preview.getPlottedPoints().add(polySpaceMousePosition);

// ask user to enter number of sides
numSides = inputVertices();

if (numSides < 3) {
// invalid input => cancel operation
// invalid input => reset state and cancel operation
disposePreview();
return;
}
return;
}
// second time clicked

// add preview as actual shape
canvasModel.getShapeManager().addShape(preview);
// generate new polygon
Polygon polygon = calculator.getRegularPolygon(firstVertex, secondVertex, numSides);
preview.setShape(polygon);

// save shape
canvasModel.getShapeManager().addShape(preview);

canvas.repaint();

disposePreview();
// discard preview
disposePreview();
}
}

@Override
Expand All @@ -76,7 +87,8 @@ protected boolean shouldDraw() {
* Asks user to enter number of vertices for polygon. If input value is invalid
* or if operation is cancelled, -1 is returned.
*
* @return
* @return The number of vertices entered by the user or -1 if invalid or
* cancelled.
*/
private int inputVertices() {
JTextField numSidesField = new JTextField(5);
Expand All @@ -99,4 +111,13 @@ private int inputVertices() {
}
return -1;
}

@Override
public void disposePreview() {
// delete any preview shape
firstVertex = null;
secondVertex = null;
preview = null;
canvasModel.getShapeManager().setShapePreview(preview);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public class PolygonCalculator {

/**
* Caches coordinates regular polygons previously calculated.
* Caches coordinates of regular polygons previously calculated.
*/
private final Map<Map.Entry<Integer, Integer>, Shape> polygonCache = new HashMap<>();

Expand All @@ -22,13 +22,12 @@ public class PolygonCalculator {
*
* @param vector A point in the x-y plane.
* @param radAngle Rotation angle in radians.
* @return
* @return The rotated vector as a Point2D.
*/
public static Point2D rotateVector(Point2D vector, double radAngle) {
return new Point2D.Double(
vector.getX() * Math.cos(radAngle) - vector.getY() * Math.sin(radAngle),
vector.getX() * Math.sin(radAngle) + vector.getY() * Math.cos(radAngle));

}

/**
Expand All @@ -37,26 +36,26 @@ public static Point2D rotateVector(Point2D vector, double radAngle) {
*
* @param point Point to be rotated.
* @param pivot Point about which rotation takes place.
* @param radAngle Rotation angle in radians.
* @return
* @param radAngle Anti-clockwise rotation angle in radians.
* @return The rotated point as a Point2D.
*/
public static Point2D rotatePointAboutPivot(Point2D point, Point2D pivot, double radAngle) {
// calculate translation vector from pivot to point
// Calculate translation vector from pivot to point
Point2D translationVector = new Point2D.Double(point.getX() - pivot.getX(), point.getY() - pivot.getY());

// rotate translation vector
// Rotate translation vector
translationVector = rotateVector(translationVector, radAngle);

// return new position of point
// Return new position of point
return new Point2D.Double(translationVector.getX() + pivot.getX(), translationVector.getY() + pivot.getY());
}

/**
* Calculates coordinates of a regular polygon centered at origin.
* Calculates coordinates of a regular polygon centered at the origin.
*
* @param sidesCount Number of sides in polygon
* @param length Side length of polygon
* @return
* @param sidesCount Number of sides in polygon.
* @param length Side length of polygon.
* @return The shape representing the polygon.
*/
private Shape getRegularPolygon(int sidesCount, int length) {
if (polygonCache.containsKey(Map.entry(sidesCount, length))) {
Expand All @@ -71,7 +70,7 @@ private Shape getRegularPolygon(int sidesCount, int length) {
length * Math.cos(rotationAngleInRad / 2));

for (int i = 1; i < sidesCount; i++) {
// rotate the previous point by the required angle
// Rotate the previous point by the required angle
Point2D.Double vector = new Point2D.Double(points[i - 1].x, points[i - 1].y);
Point2D rotatedVector = rotateVector(vector, rotationAngleInRad);
points[i] = new Point2D.Double(rotatedVector.getX(), rotatedVector.getY());
Expand All @@ -90,13 +89,56 @@ private Shape getRegularPolygon(int sidesCount, int length) {
}

/**
* Calculates integer coordinates of a regular polygon.
* Calculates a regular polygon given two adjacent vertices and the number of
* sides.
*
* @param pointA First vertex.
* @param pointB Second vertex (adjacent to the first).
* @param sidesCount Number of sides in polygon.
* @return The Polygon object representing the regular polygon.
*/
public Polygon getRegularPolygon(Point2D pointA, Point2D pointB, int sidesCount) {
final Point2D.Double[] points = new Point2D.Double[sidesCount];
points[0] = new Point2D.Double(pointA.getX(), pointA.getY());
points[1] = new Point2D.Double(pointB.getX(), pointB.getY());

/**
* Size of 1 interior angle of polygon.
*/
final double interiorAngle = (180 * (sidesCount - 2)) / (double) sidesCount;

/**
* Anticlockwise rotation angle mapping one edge to another.
*/
final double rotationAngleInRad = Math.toRadians(360 - interiorAngle);

for (int i = 2; i < sidesCount; i++) {
Point2D pivot = points[i - 1];
Point2D vectorStart = points[i - 2];

// rotate vector about pivot
points[i] = (Point2D.Double) rotatePointAboutPivot(vectorStart, pivot, rotationAngleInRad);
}

/// round off pixel coordinates to the nearest integer
int[] x = new int[sidesCount];
int[] y = new int[sidesCount];
for (int i = 0; i < sidesCount; i++) {
x[i] = (int) Math.round(points[i].x);
y[i] = (int) Math.round(points[i].y);
}

return new Polygon(x, y, sidesCount);
}

/**
* Retrieves the ordered points of a regular polygon with specified parameters.
*
* @param sidesCount number of sides
* @param length side length of polygon
* @param centerX x-coordinate of center of polygon
* @param centerY y-coordinate of center of polygon
* @return
* @param sidesCount Number of sides.
* @param length Side length.
* @param centerX X-coordinate of the polygon center.
* @param centerY Y-coordinate of the polygon center.
* @return A 2D array containing ordered x and y points.
*/
public int[][] getOrderedPoints(int sidesCount, int length, int centerX, int centerY) {
Shape polygon = getRegularPolygon(sidesCount, length);
Expand All @@ -117,11 +159,11 @@ public int[][] getOrderedPoints(int sidesCount, int length, int centerX, int cen
}

/**
* Transforms a given Polygon using the specified AffineTransform.
* Transforms a polygon using the given affine transformation.
*
* @param polygon the Polygon to be transformed
* @param transform the AffineTransform to be applied
* @return a new Polygon representing the transformed shape
* @param polygon The polygon to be transformed.
* @param transform The affine transformation to apply.
* @return The transformed polygon.
*/
public static Polygon transformPolygon(Polygon polygon, AffineTransform transform) {
Shape transformedShape = transform.createTransformedShape(polygon);
Expand Down

0 comments on commit b872710

Please sign in to comment.