I am writing my own PathIterator implementation.
Currently I implemented method with flatness with flatness-less one:
#Override
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return getPathIterator(at);
}
i.e. I am ignoring it.
What is the simplest way to work with flatness parameter?
My current iterator gives a series of parallel vertical lines (not connected between). How important for me to implement flatness-aware version of the iterator? Where is it used?
The getPathIterator() cited should return only SEG_MOVETO, SEG_LINETO, and SEG_CLOSE segment types. If your Shape has no other segment types, e.g. SEG_CUBICTO or SEG_QUADTO, the flatness is irrelevant. As a concrete example, the Rectangle2D implementation specifies that "Since rectangles are already flat, the flatness parameter is ignored."
Related
I am creating an Android app that draws to the canvas. For this, I have defined rectangular screenareas that I want to draw to the canvas. As I am always drawing a fixed set of screenareas, I was thinking of using Enum (as Enum is designed for fixed sets).
Here is my enum:
public enum LayoutEnum {
FULLSCREEN(
new ScreenArea(
new Rect(
0,
0,
MainActivity.getDevice().getWidth(),
MainActivity.getDevice().getHeight()),
Attributes.BG_PAINT)),
LOGO_AREA(
new ScreenArea (
new Rect(
(int) (0.3 * FULLSCREEN.getScreenArea().getArea().width()),
(int) (0.3 * FULLSCREEN.getScreenArea().getArea().width()),
(int) (FULLSCREEN.getScreenArea().getArea().width() - 0.3 * FULLSCREEN.getScreenArea().getArea().width()),
(int) (0.7 * FULLSCREEN.getScreenArea().getArea().width())),
Attributes.BG_PAINT)
);
private ScreenArea screenArea;
LayoutEnum(ScreenArea screenArea) {
this.screenArea = screenArea;
}
public ScreenArea getScreenArea() {
return screenArea;
}
}
ScreenArea is a simple class that holds a Rect and a Paint and contains a draw method (and some getters and setters).
The question I have, is: is this a good approach?
On one hand I am working with a fixed set of variables. On the other hand, these variables are mutable and I can change their attributes (e.g., using the getters and setters). For example, I can call FULLSCREEN.getScreenArea().getPaint().setColor(Color.BLUE)
When you look at Enum it says it is
a special data type that enables for a variable to be a set of
predefined constant
So I do have a fixed set, it is predefined, but not necessarily constant.
My original approach was to define a class called Layout which contained a HashMap of Screenarea's. In that case, I was using e.g., Layout.get("fullscreen").draw(canvas) to draw the screenarea to the canvas. In this new approach I am using e.g., FULLSCREEN.getScreenArea().draw(canvas).
One of the reasons I would like to switch is to introduce a typesafe solution. Of course, it would also be possible to switch from a HashMap to an EnumMap and store the names of my screenareas in an Enum.
Hope you can point me in the right direction: a direction that not only works (the above is already working) but is also acceptable and doesn't smell.
I would rather not use any third party JARs or AWT as part of this solution. I am doing everything in my power to keep my project dependency-free. And, if the JRE ships with any classes that solve this for me, I'm still interested in a custom solution here so that I can really understand the mathematics and not just blindly make a few API calls.
I have the following POJO structure for various shapes:
public class Coordinate {
private Double xVal;
private Double yVal;
// Constructors, getters/setters, etc.
public static Double distance(Coordinate c1, Coordinate c2) {
// Calculates the Cartesian distance between c1 and c2 using the standard
// distance formula.
}
}
public abstract class Shape {
// Some properties inherent to all 2D shapes.
public abstract Double calcArea();
public abstract Double calcPerimeter();
}
public class Rectangle extends Shape {
private Coordinate upperLeft;
private Coordinate upperRight;
private Coordinate lowerLeft;
private Coordinate lowerRight;
// Constructors, overrides, getters/setters, etc.
}
public class Circle extends Shape {
private Coordinate center;
private Double radius;
// Constructors, overrides, getters/setters, etc.
}
Now then, I will be given a List<Shape> (mixed set containing 0+ Rectangles and 0+ Circles). I need to determine if any of the shapes in this list intersect with each other (true or false):
public boolean intersectionsExist(List<Shape> shapes) {
// ???
}
I'd like to implement best practices here, so I don't know if there is already any algorithm to do this with (potentially) dozens of shapes. All the "intersection detection" code snippets I've found on SO and on the web have been between exactly 2 shapes. But what if I have 3 rectangles and 7 circles in the list?!?
My thinking is to iterate through each Shape in the list, and compare it with every other Shape (hence a quadratic solution, which I'm not thrilled about). But that way, I could return true the instant I find a Shape that intersects with another.
As for detecting the actual intersection, I am wondering if there is anything I can do that treats these shapes like a Venn diagram. Meaning, somehow determine if one shape is overlapping another. But as to how I could determine "overlap", I have no idea.
So several questions:
Are there any standard algorithms out there for detecting intersections among 3+ shapes? If so, can someone please give me some links/info on them?
If the answer to #1 above is "no", then is my quadratic solution above the best way to go (double-nested for-loops comparing each Shape to every other, and returning true when one intersection is found)? Or is there a better/more efficient way?
Most importantly: how to detect the actual intersections? Are there standard algorithms to accomplish this (links?)? Can someone provide a code example (using my POJOs above), or even give a simple pseudo-code example of what I could do here?
Your problem is commonly called Constructive Solid Geometry. Lookup Wikipedia and or a standard book about computer graphics but please don't expect working code about this complex stuff as a ready-to-use answer.
There are varying solutions for collision detection. You can handle detection within a huge array of objects, as with modern games and their thousands of models, but you are only ever comparing collision for two items at a time
The fastest and simplest-to-code option is to use circles that encompass your objects(very easy if your object is circular) and use a distance-between test. If the distance between the two circles' center points is less than their combined radii, then they are colliding.
This option has some drawbacks, such as a circle on a rectangular object will either collide in some areas where the rectangle isn't drawn(if the circle is larger than the rect) or won't collide at some times it should(if the circle is smaller than the rect).
Some other things you can look at are Axis-Aligned Bounding Boxes or n-DOP collision, both of which are somewhat more mathematically intensive. Here's a good general collisions tutorial
If you want to get extremely complicated and mathy, here is a method known as SAT(Separating Axis Theorem) http://www.metanetsoftware.com/technique/tutorialA.html
If you're interested in the theory of intersections, there is an analysis of the problem in a paper by Chazelle and Dobkin of Princeton†. The paper is too long to summarize here, but it provides a lengthy step-by-step algorithm with proofs. You would still need to code the algorithm yourself. However, the OP did ask for links and/or references.
†Chazelle, B., and Daniel P. Dobkin. Intersection of Convex Objects in Two and Three Dimensions. Princeton, NJ: Princeton U, Dept. of Computer Science, 1986. Web.
Let's say for example a vector is composed of some objects, one of type rectangle, some of type triangle, and then circles.
v = [rectangle, triangle, triangle, circle, circle]
The vector's size can change. I can add another circle as so:
v.addElement(circle);
and..
v = [rectangle, triangle, triangle, circle, circle, circle]
but each object type is clustered together like above. It can't be like:
v = [rectangle, circle, circle, triangle, circle, triangle] //<-- can't be.
I know I explained it pretty horrible but hopefully, it's enough to understand my scenario. Now, I want to randomly choose, for example, an object of type circle.
My thought process is to make a separate method that 1, finds the beginning index and 2, find the ending index and then use random functions off of that. Is there a more elegant way to solve this problem of only choosing randomly off of circles?
Use the Collections API:
Collections.shuffle(v);
Object random = v.get(0);
You should use a hashmap and map the object class as the key and a corresponding array of objects of that class. You can yse reflection to get the class name and set as the key, then add the object to the array as the value.
Otherwise you can't group similar objects in the array and choose a random object from a set of similar objects in an array of different classes like you asked... Unless you framed your question incorrectly
This sounds like a fairly simple random pick problem. All you need to do is generate a random number and get that element -
v.get(Random.nextInt(v.size()));
You can potentially use the implements keyword to check if an object is of a type (or a subtype of that type), but this is not a very pretty solution.
The best solution would likely be to control read and write access to this vector; basically, if you have specific methods for inserting the different shapes, you can stay in control and always ensure that things are inserted to the right place. At that point, just store two ints or such to know where the second and third sections start when choosing.
Although personally, I would just use three separate vectors, if that's possible.
I'm creating a 2D game in Java using the Java2D library for drawing, and I really need a float-precision Polygon object that I can use both to draw game objects and to do collision detection on them. Unfortunately, Java's Polygon object comes in int precision only, and there is no equivalent Polygon2D like there is with Rectangle and Rectangle2D. I've already done enough research to see that I have a few options, but none of them seem very good.
Use Path2D. According to a Java developer posting in this forum, the lack of Polygon2D was an oversight, but its suggested replacement is Path2D. Unfortunately, Path2D doesn't provide a way to access its individual vertices or edges, which I need in order to do collision detection (specifically I need to get a vector orthogonal to each edge).
Implement my own Polygon2D that implements the Shape interface so that I can still pass it to Graphics2D.draw(Shape). This looks like it would be pretty difficult. The Shape interface requires tricky-to-implement methods like contains(Rectangle2D) and getPathIterator(AffineTransform). For getPathIterator in particular, it seems that in order to implement it I'd need to return an object of type PathIterator, but there are no concrete implementations of the PathIterator interface available in the public AWT packages.
Wrap Path2D in an object that "remembers" the individual vertices and provides them to the client. This worked for me when I needed an Area that remembered its component shapes: I wrapped it in a CompoundShape class that implemented the Shape interface and forwarded all the Shape methods to Area's implementation of them, while keeping track of each Shape that was added to the Area in an ArrayList. The problem with this is that if I keep track of the individual vertices in two arrays of floats, there is no way to expose them to the user without the possibility of the user changing the vertices - and since that would happen by direct array access, the internal Path2D wouldn't get notified of the changes.
Copy Polygon.java. The actual source code of Java's Polygon class is available on grepcode.com, and I could simply replace the vertex-related ints with floats throughout to get a Polygon2D. Unfortunately, when I tried this, the line import sun.awt.geom.Crossings; threw a compiler error saying "The type Crossings is not accessible due to restriction on required library C:\Program Files\Java\jre7\lib\rt.jar." According to this question that happens because Sun's license agreement prevents you from replacing core Java classes with your own, but Polygon doesn't try to do that - it simply creates an object of type sun.awt.geom.Crossings, no replacing or extending happens, and I made sure to put my copy of Polygon in a package not called "java".
What's the best way to proceed with this? I'd appreciate either suggestions for how make one of these options work or an idea for another option that doesn't have the problems these encounter.
I would also recommend Path2D. GeneralPath is a legacy class; don't use it.
Path2D does provide access to the vertex values, albeit it a roundabout fashion. You need to use a PathIterator:
PathIterator pi = path.getPathIterator(null);
float[] value = new float[6];
float x = 0, y = 0;
while (!pi.isDone()) {
int type = pi.currentSegment(values);
if (type == PathIterator.SEG_LINETO) {
x = values[0];
y = values[1];
}
else if (type == PathIterator.SEG_CLOSE) {
x = 0;
y = 0;
}
else {
// SEG_MOVETO, SEG_QUADTO, SEG_CUBICTO
}
pi.next();
}
When you're ready to get fancy, you can expand that else to support the quadratic and cubic curves.
I assume you don't need those at this time as you're talking about polygons.
Also, Path2D has some handy static methods for testing whether the path intersects a rectangle and whether the path contains a rectangle or point. Sadly, there are no methods for testing for a path intersecting or containing another path.
Perhaps have the internals of the polygon at a different scale?
Multiply by a large number and typecast to int when writing to it, divide by the same large number when reading?
Can you use a 3rd party library? If so, might I suggest to use the Slick 2D Polygon class. What I would do is internally, use this class for your actual Polygon to check intersection with contains and then when you need to draw, just cast the float values to int and draw the Java2D Polygon.
I know this might not be the optimal solution, but it might work for what you're doing.
I want to use shape to diagnose the border points in a map, How can i use this class in java for diagnosing these points so that i can put something on these areas or move something on them ? How can i do it ?
FlatteningPathIterator
From comment
* The FlatteningPathIterator class returns a flattened view of
* another {#link PathIterator} object. Other {#link java.awt.Shape Shape}
* classes can use this class to provide flattening behavior for their paths
* without having to perform the interpolation calculations themselves.