Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Shapes #121

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package de.unistuttgart.informatik.fius.jvk.provided.shapes;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.lang.Math;
import de.unistuttgart.informatik.fius.icge.simulation.Position;


/**
* A finite length line shape.
*/
public class Circle implements Shape {

private List<Position> points;

/**
* Create a Circle, at the middle of the field. With the radius 1;
*
*/
public Circle() {
this(new Position(0, 0), 1);
}

/**
* Create a Circle, at the middle of the field
*
* @param radius
* the radius of the circle
*/
public Circle(Integer radius) {
this(new Position(0, 0), radius);
}


/**
* Create a Circle
*
* @param middle
* the center of the circle
* @param radius
* the radius of the circle
*/
public Circle(Position middle, Integer radius) {
Integer deltaX = middle.getX();
Integer deltaY = middle.getY();

List<Position> points = new ArrayList<>();
List<Position> pointsAdd = new ArrayList<>();
for(Integer x = 0; x < radius;x++){
Double y = Math.sin(Math.acos(x.doubleValue()/radius))*radius;
points.add(new Position(x,(int)Math.round(y)));
}
for(Integer y = 0; y < radius;y++){
Double x = Math.cos(Math.asin(y.doubleValue()/radius))*radius;
Position position = new Position((int)Math.round(x),y);
if(!points.contains(position)){
points.add(position);
}
}
points.forEach(p -> pointsAdd.add(new Position(p.getX(), -1*p.getY())));
pointsAdd.forEach(p -> {if(!points.contains(p))points.add(p);} );
pointsAdd.clear();
points.forEach(p -> pointsAdd.add(new Position(-1*p.getX(), p.getY())));
pointsAdd.forEach(p -> {if(!points.contains(p))points.add(p);} );
pointsAdd.clear();
points.forEach(p->{
pointsAdd.add(new Position(p.getX()+middle.getX(), p.getY()+middle.getY()));
});
this.points=pointsAdd;
}

@Override
public Iterator<Position> iterator() {
return this.points.iterator();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package de.unistuttgart.informatik.fius.jvk.provided.shapes;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;

import de.unistuttgart.informatik.fius.icge.simulation.Position;

/**
* A shape created by filling out an existing shape.
*/
public class FilledShape implements Shape {

private Set<Position> points;

/**
* Create a new shape by filling out the given shape.
*
* @param shape the input shape
*/
public FilledShape(Shape shape) {
Set<Position> points = new HashSet<>();

points.addAll(shape);

if (points.isEmpty()) {
this.points = points;
return;
}

// calc bounding box...
Integer x1 = Integer.MAX_VALUE;
Integer x2 = Integer.MIN_VALUE;
Integer y1 = Integer.MAX_VALUE;
Integer y2 = Integer.MIN_VALUE;
for (Position pos : points) {
if (pos.getX() < x1) {
x1 = pos.getX();
}
if (pos.getX() > x2) {
x2 = pos.getX();
}
if (pos.getY() < y1) {
y1 = pos.getY();
}
if (pos.getY() > y2) {
y2 = pos.getY();
}
Comment on lines +39 to +50
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (pos.getX() < x1) {
x1 = pos.getX();
}
if (pos.getX() > x2) {
x2 = pos.getX();
}
if (pos.getY() < y1) {
y1 = pos.getY();
}
if (pos.getY() > y2) {
y2 = pos.getY();
}
x1 = Math.min(x1, pos.getX());
x2 = Math.max(x2, pos.getX());
y1 = Math.min(y1, pos.getY());
y2 = Math.min(y2, pos.getY());

}

Set<Position> outside = new HashSet<>();
for (Integer y = y1; y <= y2; y++) {
outside.add(new Position(x1-1, y));
outside.add(new Position(x2+1, y));
}
for (Integer x = x1; x <= x2; x++) {
outside.add(new Position(x, y1-1));
outside.add(new Position(x, y2+1));
}

Set<Position> visited = new HashSet<>();
Stack<Position> stack = new Stack<>();

// flood fill outside
stack.push(new Position(x1-1, y1-1));
while (!stack.isEmpty()) {
Position current = stack.pop();
if (visited.contains(current)) {
continue;
}
visited.add(current);
if (current.getX() < x1 - 1) continue;
if (current.getX() > x2 + 1) continue;
if (current.getY() < y1 - 1) continue;
if (current.getY() > y2 + 1) continue;
if (!points.contains(current)) {
outside.add(current);

stack.push(new Position(current.getX(), current.getY()-1));
stack.push(new Position(current.getX()-1, current.getY()));
stack.push(new Position(current.getX(), current.getY()+1));
stack.push(new Position(current.getX()+1, current.getY()));
}
}


// flood fill inside
visited.clear();
for (Position pos : points) {
stack.push(pos);
}
while (!stack.isEmpty()) {
Position current = stack.pop();
if (visited.contains(current)) {
continue;
}
visited.add(current);
if (!outside.contains(current)) {
points.add(current);

stack.push(new Position(current.getX(), current.getY()-1));
stack.push(new Position(current.getX()-1, current.getY()));
stack.push(new Position(current.getX(), current.getY()+1));
stack.push(new Position(current.getX()+1, current.getY()));
}
}

this.points = points;
}

@Override
public Iterator<Position> iterator() {
return this.points.iterator();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,51 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import java.lang.Math;
import de.unistuttgart.informatik.fius.icge.simulation.Position;


/**
* A finite length line shape that is always parallel to the coordinate axes.
* A finite length line shape.
*/
public class Line implements Shape {

private List<Position> points;

/**
* Create a new line by specifying start and end position of the line.
*
* @param start the start of the line
* @param end the end of the line; may not differ from the line start in both x and y direction
* @param start
* the start of the line
* @param end
* the end of the line; may not differ from the line start in both x and y direction
*/
public Line(Position start, Position end) {
Integer deltaX = start.getX() - end.getX();
Integer deltaY = start.getY() - end.getY();

if (deltaX != 0 && deltaY != 0) {
throw new IllegalArgumentException("Only lines parallel to the grid are supported.");
}

Integer deltaX = end.getX() - start.getX();
Integer deltaY = end.getY() - start.getY();
Double slope; //slope needs to have digits after the . ,so Float is used
List<Position> points = new ArrayList<>();
points.add(start);

Position currentPos = start;
while (deltaX != 0 || deltaY != 0) {
if (deltaX > 0) {
currentPos = new Position(currentPos.getX() - 1, currentPos.getY());
points.add(currentPos);
deltaX -= 1;
}
if (deltaX < 0) {
currentPos = new Position(currentPos.getX() + 1, currentPos.getY());
points.add(currentPos);
deltaX += 1;

if (Math.abs(deltaX) > Math.abs(deltaY)) {
slope = deltaY.doubleValue() / deltaX.doubleValue();
for (Integer x = start.getX(); (deltaX > 0) ? x <= end.getX() : x >= end.getX(); x += ((deltaX > 0 ? 1 : -1))) {
Integer y = (int)Math.round(x.doubleValue() * slope+start.getY());
points.add(new Position(x, y));
}
if (deltaY > 0) {
currentPos = new Position(currentPos.getX(), currentPos.getY() - 1);
points.add(currentPos);
deltaY -= 1;
}
if (deltaY < 0) {
currentPos = new Position(currentPos.getX(), currentPos.getY() + 1);
points.add(currentPos);
deltaY += 1;
}
else{
slope = deltaX.doubleValue() / deltaY.doubleValue();
for(Integer y = start.getY(); (deltaY > 0) ? y <= end.getY() : y >= end.getY(); y += ((deltaY > 0 ? 1 : -1))){
Integer x = (int)Math.round(y.doubleValue() * slope +start.getX());
points.add(new Position(x, y));
}
}

this.points = points;
}

@Override
public Iterator<Position> iterator() {
return this.points.iterator();
}

}
}