How to create grid coverage when each cell is 5M ?
I found this :
GridCoverage2D coverage = reader.read(null);
// direct access
DirectPosition position = new DirectPosition2D(crs, x, y);
double[] sample = (double[]) coverage.evaluate(position); // assume double
// resample with the same array
sample = coverage.evaluate(position, sample);
Source : https://docs.geotools.org/latest/userguide/library/coverage/grid.html
I didn't found a lot of tutorial about how to create grid coverage on geotools...
To create an empty coverage you need to use the GridCoverageFactory and one of the create methods. Since you are not constructing from an existing image you need to provide some memory for your raster to be stored in (this can also hold any initial values you want). For this your choices are a float[][] or a WritableRaster. Finally, you need a Envelope to say where the coverage is and what it's resolution is (otherwise it is just an array of numbers), I favour using a ReferencedEnvelope so that I know what the units are etc, so in the example below I have used EPSG:27700 which is the OSGB national grid so I know that it is in metres and I can define the origin somewhere in the South Downs. By specifying the lower left X and Y coordinates and the upper right X and Y as resolution times the width and height (plus the lower left corner) the maths all works out to make sure that the size of my pixels is resolution.
So keeping it simple for now you could do something like:
float[][] data;
int width = 100;
int height = 200;
data = new float[width][height];
int resolution = 5;
for(int i=0;i<width;i++){
for(int j=0;j<height;j++ ){
data[i][j] = 0.0f;
}
}
GridCoverageFactory gcf = new GridCoverageFactory();
CoordinateReferenceSystem crs = CRS.decode("EPSG:27700");
int llx = 500000;
int lly = 105000;
ReferencedEnvelope referencedEnvelope = new ReferencedEnvelope(llx, llx + (width * resolution), lly, lly + (height * resolution),
crs);
GridCoverage2D gc = gcf.create("name", data, referencedEnvelope);
If you want more bands in your coverage then you need to use a WriteableRaster as the base for your coverage.
WritableRaster raster2 = RasterFactory.createBandedRaster(java.awt.image.DataBuffer.TYPE_INT, width,
height, 3, null);
for (int i = 0; i < width; i++) {//width...
for (int j = 0; j < height; j++) {
raster2.setSample(i, j, 0, rn.nextInt(200));
raster2.setSample(i, j, 1, rn.nextInt(200));
raster2.setSample(i, j, 2, rn.nextInt(200));
}
}
Related
Hi I am in need of some help. I need to write a convolution method from scratch that takes in the following inputs: int[][] and BufferedImage inputImage. I can assume that the kernel has size 3x3.
My approach is to do the follow:
convolve inner pixels
convolve corner pixels
convolve outer pixels
In the program that I will post below I believe I convolve the inner pixels but I am a bit lost at how to convolve the corner and outer pixels. I am aware that corner pixels are at (0,0), (width-1,0), (0, height-1) and (width-1,height-1). I think I know to how approach the problem but not sure how to execute that in writing though. Please to aware that I am very new to programming :/ Any assistance will be very helpful to me.
import java.awt.*;
import java.awt.image.BufferedImage;
import com.programwithjava.basic.DrawingKit;
import java.util.Scanner;
public class Problem28 {
// maximum value of a sample
private static final int MAX_VALUE = 255;
//minimum value of a sample
private static final int MIN_VALUE = 0;
public BufferedImage convolve(int[][] kernel, BufferedImage inputImage) {
}
public BufferedImage convolveInner(double center, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage1 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 1; x < width - 1; x++) {
for (int y = 1; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) center*red;
int innergreen = (int) center*green;
int innerblue = (int) center*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage1.setRGB(x, y, newRgbvalue);
}
}
return inputImage1;
}
public BufferedImage convolveEdge(double edge, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 0; x < width - 1; x++) {
for (int y = 0; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) edge*red;
int innergreen = (int) edge*green;
int innerblue = (int) edge*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage2.setRGB(x, y, newRgbvalue);
}
}
return inputImage2;
}
public BufferedImage convolveCorner(double corner, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage3 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 0; x < width - 1; x++) {
for (int y = 0; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) corner*red;
int innergreen = (int) corner*green;
int innerblue = (int) corner*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage3.setRGB(x, y, newRgbvalue);
}
}
return inputImage3;
}
public static void main(String[] args) {
DrawingKit dk = new DrawingKit("Compositor", 1000, 1000);
BufferedImage p1 = dk.loadPicture("image/pattern1.jpg");
Problem28 c = new Problem28();
BufferedImage p5 = c.convolve();
dk.drawPicture(p5, 0, 100);
}
}
I changed the code a bit but the output comes out as black. What did I do wrong:
import java.awt.*;
import java.awt.image.BufferedImage;
import com.programwithjava.basic.DrawingKit;
import java.util.Scanner;
public class Problem28 {
// maximum value of a sample
private static final int MAX_VALUE = 255;
//minimum value of a sample
private static final int MIN_VALUE = 0;
public BufferedImage convolve(int[][] kernel, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage1 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//for every pixel
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
int colorValue = inputImage.getRGB(x,y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed();
int green = pixelColor.getGreen();
int blue = pixelColor.getBlue();
double gray = 0;
//multiply every value of kernel with corresponding image pixel
for (int i = 0; i < 3; i ++) {
for (int j = 0; j < 3; j ++) {
int imageX = (x - 3/2 + i + width) % width;
int imageY = (x -3/2 + j + height) % height;
int RGB = inputImage.getRGB(imageX, imageY);
int GRAY = (RGB) & 0xff;
gray += (GRAY*kernel[i][j]);
}
}
int out;
out = (int) Math.min(Math.max(gray * 1, 0), 255);
inputImage1.setRGB(x, y, new Color(out,out,out).getRGB());
}
}
return inputImage1;
}
public static void main(String[] args) {
int[][] newArray = {{1/9, 1/9, 1/9}, {1/9, 1/9, 1/9}, {1/9, 1/9, 1/9}};
DrawingKit dk = new DrawingKit("Problem28", 1000, 1000);
BufferedImage p1 = dk.loadPicture("image/pattern1.jpg");
Problem28 c = new Problem28();
BufferedImage p2 = c.convolve(newArray, p1);
dk.drawPicture(p2, 0, 100);
}
}
Welcome ewuzz! I wrote a convolution using CUDA about a week ago, and the majority of my experience is with Java, so I feel qualified to provide advice for this problem.
Rather than writing all of the code for you, the best way to solve this large program is to discuss individual elements. You mentioned you are very new to programming. As the programs you write become more complex, it's essential to write small working snippets before combining them into a large successful program (or iteratively add snippets). With this being said, it's already apparent you're trying to debug a ~100 line program, and this approach will cost you time in most cases.
The first point to discuss is the general approach you mentioned. If you think about the program, what is the simplest and most repeated step? Obviously this is the kernel/mask step, so we can start from here. When you convolute each pixel, you are performing a similar option, regardless of the position (corner, edge, inside). While there are special steps necessary for these edge cases, they share similar underlying steps. If you try to write code for each of these cases separately, you will have to update the code in multiple (three) places with each adjustment and it will make the whole program more difficult to grasp.
To support my point above, here's what happened when I pasted your code into IntelliJ. This illustrates the (yellow) red flag of using the same code in multiple places:
The concrete way to fix this problem is to combine the three convolve methods into a single one and use if statements for edge-cases as necessary.
Our pseudocode with this change:
convolve(kernel, inputImage)
for each pixel in the image
convolve the single pixel and check edge cases
endfor
end
That seems pretty basic right? If we are able to successfully check edge cases, then this extremely simple logic will work. The reason I left it so general above to show how convolve the single pixel and check edge cases is logically grouped. This means it's a good candidate for extracting a method, which could look like:
private void convolvePixel(int x, int y, int[][] kernel, BufferedImage input, BufferedImage output)
Now to implement our method above, we will need to break it into a few steps, which we may then break into more steps if necessary. We'll need to look at the input image, if possible for each pixel accumulate the values using the kernel, and then set this in the output image. For brevity I will only write pseudocode from here.
convolvePixel(x, y, kernel, input, output)
accumulation = 0
for each row of kernel applicable pixels
for each column of kernel applicable pixels
if this neighboring pixel location is within the image boundaries then
input color = get the color at this neighboring pixel
adjusted value = input color * relative kernel mask value
accumulation += adjusted value
else
//handle this somehow, mentioned below
endif
endfor
endfor
set output pixel as accumulation, assuming this convolution method does not require normalization
end
The pseudocode above is already relatively long. When implementing you could write methods for the if and the else cases, but it you should be fine with this structure.
There are a few ways to handle the edge case of the else above. Your assignment probably specifies a requirement, but the fancy way is to tile around, and pretend like there's another instance of the same image next to this input image. Wikipedia explains three possibilities:
Extend - The nearest border pixels are conceptually extended as far as necessary to provide values for the convolution. Corner pixels are extended in 90° wedges. Other edge pixels are extended in lines.
Wrap - (The method I mentioned) The image is conceptually wrapped (or tiled) and values are taken from the opposite edge or corner.
Crop - Any pixel in the output image which would require values from beyond the edge is skipped. This method can result in the output image being slightly smaller, with the edges having been cropped.
A huge part of becoming a successful programmer is researching on your own. If you read about these methods, work through them on paper, run your convolvePixel method on single pixels, and compare the output to your results by hand, you will find success.
Summary:
Start by cleaning-up your code before anything.
Group the same code into one place.
Hammer out a small chunk (convolving a single pixel). Print out the result and the input values and verify they are correct.
Draw out edge/corner cases.
Read about ways to solve edge cases and decide what fits your needs.
Try implementing the else case through the same form of testing.
Call your convolveImage method with the loop, using the convolvePixel method you know works. Done!
You can look up pseudocode and even specific code to solve the exact problem, so I focused on providing general insight and strategies I have developed through my degree and personal experience. Good luck and please let me know if you want to discuss anything else in the comments below.
Java code for multiple blurs via convolution.
I'm currently trying to develop a ArUco cube detector for a project. The goal is to have a more stable and accurate pose estimation without using a large ArUco board. For this to work however, I need to know the orientation of each of the markers. Using the draw3dAxis method, I discovered that the X and Y axis did not consistently appear in the same location. Here is a video demonstrating the issue: https://youtu.be/gS7BWKm2nmg
It seems to be a problem with the Rvec detection. There is a clear shift in the first two values of the Rvec, which will stay fairly consistent until the axis swaps. When this axis swap happens the values can change by a magnitude anywhere from 2-6. The ARuco library does try to deal with rotations as shown in the Marker.calculateMarkerId() method:
/**
* Return the id read in the code inside a marker. Each marker is divided into 7x7 regions
* of which the inner 5x5 contain info, the border should always be black. This function
* assumes that the code has been extracted previously.
* #return the id of the marker
*/
protected int calculateMarkerId(){
// check all the rotations of code
Code[] rotations = new Code[4];
rotations[0] = code;
int[] dists = new int[4];
dists[0] = hammDist(rotations[0]);
int[] minDist = {dists[0],0};
for(int i=1;i<4;i++){
// rotate
rotations[i] = Code.rotate(rotations[i-1]);
dists[i] = hammDist(rotations[i]);
if(dists[i] < minDist[0]){
minDist[0] = dists[i];
minDist[1] = i;
}
}
this.rotations = minDist[1];
if(minDist[0] != 0){
return -1; // matching id not found
}
else{
this.id = mat2id(rotations[minDist[1]]);
}
return id;
}
and the MarkerDetector.detect() does call that method and uses the getRotations() Method:
// identify the markers
for(int i=0;i<nCandidates;i++){
if(toRemove.get(i) == 0){
Marker marker = candidateMarkers.get(i);
Mat canonicalMarker = new Mat();
warp(in, canonicalMarker, new Size(50,50), marker.toList());
marker.setMat(canonicalMarker);
marker.extractCode();
if(marker.checkBorder()){
int id = marker.calculateMarkerId();
if(id != -1){
// rotate the points of the marker so they are always in the same order no matter the camera orientation
Collections.rotate(marker.toList(), 4-marker.getRotations());
newMarkers.add(marker);
}
}
}
}
The full source code for the ArUco library is here: https://github.com/sidberg/aruco-android/blob/master/Aruco/src/es/ava/aruco/MarkerDetector.java
If anyone has any advice or solutions I'd be very gracious. Please contact me if you have any questions.
I did find the problem. It turns out that the Marker Class has a rotation variable that can be used to rotate the axis to align with the orientation of the marker. I wrote the following method in the Utils class:
protected static void alignToId(Mat rotation, int codeRotation) {
//get the matrix corresponding to the rotation vector
Mat R = new Mat(3, 3, CvType.CV_64FC1);
Calib3d.Rodrigues(rotation, R);
codeRotation += 1;
//create the matrix to rotate around Z Axis
double[] rot = {
Math.cos(Math.toRadians(90) * codeRotation), -Math.sin(Math.toRadians(90) * codeRotation), 0,
Math.sin(Math.toRadians(90) * codeRotation), Math.cos(Math.toRadians(90) * codeRotation), 0,
0, 0, 1
};
// multiply both matrix
Mat res = new Mat(3, 3, CvType.CV_64FC1);
double[] prod = new double[9];
double[] a = new double[9];
R.get(0, 0, a);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
prod[3 * i + j] = 0;
for (int k = 0; k < 3; k++) {
prod[3 * i + j] += a[3 * i + k] * rot[3 * k + j];
}
}
// convert the matrix to a vector with rodrigues back
res.put(0, 0, prod);
Calib3d.Rodrigues(res, rotation);
}
and I called it from the Marker.calculateExtrinsics Method:
Utils.alignToId(Rvec, this.getRotations());
I would like to compare two arrays to see if they have the same values.
If I have a array called
public static float data[][]
which holds Y coordinates of a terrain, how can I check that array with another
public static int coords[][]
without iterating through all the coordinates?
Both arrays have over 1000 values in them. Iterating through them is not an option, since I must iterate through them over four times per second.
I am doing this to attempt to find if two objects are colliding. I have attempted using libraries for this, however I cannot find per-coordinate collision detection as specific as I need it.
Edit: Why I am unable to just iterate through this small amount of vertices is this.
The problem is, this is a MultiPlayer game,and I would have to iterate through all 1000 coordinates for every player. Meaning that just 10 players online is 10,000 100 online is 100,000. You can see how easily that would lag or at least take up a large percentage of the CPU.
Input of coordinates into the "Data" variable:
try {
// Load the heightmap-image from its resource file
BufferedImage heightmapImage = ImageIO.read(new File(
"res/images/heightmap.bmp"));
//width = heightmapImage.getWidth();
//height = heightmapImage.getHeight();
BufferedImage heightmapColour = ImageIO.read(new File(
"res/images/colours.bmp"));
// Initialise the data array, which holds the heights of the
// heightmap-vertices, with the correct dimensions
data = new float[heightmapImage.getWidth()][heightmapImage
.getHeight()];
// collide = new int[heightmapImage.getWidth()][50][heightmapImage.getHeight()];
red = new float[heightmapColour.getWidth()][heightmapColour
.getHeight()];
blue = new float[heightmapColour.getWidth()][heightmapColour
.getHeight()];
green = new float[heightmapColour.getWidth()][heightmapColour
.getHeight()];
// Lazily initialise the convenience class for extracting the
// separate red, green, blue, or alpha channels
// an int in the default RGB color model and default sRGB
// colourspace.
Color colour;
Color colours;
// Iterate over the pixels in the image on the x-axis
for (int z = 0; z < data.length; z++) {
// Iterate over the pixels in the image on the y-axis
for (int x = 0; x < data[z].length; x++) {
colour = new Color(heightmapImage.getRGB(z, x));
data[z][x] = setHeight;
}
}
}catch (Exception e){
e.printStackTrace();
System.exit(1);
}
And how coordinates are put into the "coords" variable (Oh wait, it was called "Ship", not coords. I forgot that):
try{
File f = new File("res/images/coords.txt");
String coords = readTextFile(f.getAbsolutePath());
for (int i = 0; i < coords.length();){
int i1 = i;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String x = coords.substring(i, i1).replace(",", "");
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String y = coords.substring(i, i1).replace(",", "");;
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String z = coords.substring(i, i1).replace(",", "");;
i = i1 + 1;
//buildx.append(String.valueOf(coords.charAt(i)));
////System.out.println(x);
////System.out.println(y);
////System.out.println(z);
//x = String.valueOf((int)Double.parseDouble(x));
//y = String.valueOf((int)Double.parseDouble(y));
//z = String.valueOf((int)Double.parseDouble(z));
double sx = Double.valueOf(x);
double sy = Double.valueOf(y);
double sz = Double.valueOf(z);
javax.vecmath.Vector3f cor = new javax.vecmath.Vector3f(Float.parseFloat(x), Float.parseFloat(y), Float.parseFloat(z));
//if (!arr.contains(cor)){
if (cor.y > 0)
arr.add(new javax.vecmath.Vector3f(cor));
if (!ship.contains(new Vector3f((int) sx, (int) sy, (int) sz)))
ship.add(new Vector3f((int) sx, (int) sy, (int) sz));
// arr.add(new javax.vecmath.Vector3f(Float.parseFloat(x), Float.parseFloat(y), Float.parseFloat(z)));
}
Thanks!
You can do like this but only applicable for same data type.
Arrays.deepEquals(data, coords);
For single dimension Array you can use this
Arrays.equals(array1, array1);
Arrays.deepEquals(a, b);
Try this but this will work only if the elements are in order.
No way around it, I'm afraid. Comparing data sets to see if they are identical demands looking at all elements, by definition. On a side note, comparing 1000 values is nothing even on relatively old hardware. You can do it thousands of time per second.
I have an image that is stored as an array of pixel values. I want to be able to apply a brightness or contrast filter to this image. Is there any simple way, or algorithm, that I can use to achieve this.
Here is my code...
PlanarImage img=JAI.create("fileload","C:\\aimages\\blue_water.jpg");
BufferedImage image = img.getAsBufferedImage();
int w = image.getWidth();
int h = image.getHeight();
int k = 0;
int[] sbins = new int[256];
int[] pixel = new int[3];
Double d = 0.0;
Double d1;
for (int x = 0; x < bi.getWidth(); x++) {
for (int y = 0; y < bi.getHeight(); y++) {
pixel = bi.getRaster().getPixel(x, y, new int[3]);
k = (int) ((0.2125 * pixel[0]) + (0.7154 * pixel[1]) + (0.072 * pixel[2]));
sbins[k]++;
}
}
My suggestion would be to use the built-in methods of Java to adjust the brightness and contrast, rather than trying to adjust the pixel values yourself. It seems pretty easy by doing something like this...
float brightenFactor = 1.2f
PlanarImage img=JAI.create("fileload","C:\\aimages\\blue_water.jpg");
BufferedImage image = img.getAsBufferedImage();
RescaleOp op = new RescaleOp(brightenFactor, 0, null);
image = op.filter(image, image);
The float number is a percentage of the brightness. In my example it would increase the brightness to 120% of the existing value (ie. 20% brighter than the original image)
See this link for a similar question...
Adjust brightness and contrast of BufferedImage in Java
See this link for an example application...
http://www.java2s.com/Code/Java/Advanced-Graphics/BrightnessIncreaseDemo.htm
I created a program to draw many polygons automatically everytimes user presses a button. The points of the polygon are generated automatically using the random function. The problem is that, since the points of the polygon were randomly generated, some of the polygon are overlap with other polygon. How can I avoid this, so that every polygon shown without being overlapped?
.....
List<Polygon> triangles = new LinkedList<Polygon>();
Random generator = new Random();
public void paintComponent(Graphics g) {
for(int i = 0; i < 10; i++) {
double xWidth = generator.nextDouble() * 40.0 + 10.0;
double yHeight = generator.nextDouble() * 40.0 + 10.0;
xCoord[0] = generator.nextInt(MAX_WIDTH);
yCoord[0] = generator.nextInt(MAX_HEIGHT);
xCoord[1] = (int) (xCoord[0] - xWidth);
xCoord[2] = (int) (xCoord[1] + (xWidth/2));
yCoord[1] = yCoord[0];
yCoord[2] = (int) (yCoord[1] - yHeight);
triangles.add( new Polygon(xCoord,yCoord, 3));
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.00f));
g2.setPaint(Color.black);//set the polygon line
for (Polygon triangle : triangles) g2.drawPolygon(triangle);
Polygon[] triArray = triangles.toArray(new Polygon[triangles.size()]);
for (Polygon p:triArray) triangles.remove (p);
}
Check out the game programming wiki on Polygon Collision:
http://gpwiki.org/index.php/Polygon_Collision
You could break your canvas into 10 regions and constrain your polygons each to their own region. To do this, you could use your i value and a %100 (or other suitable magnitude) of your randomly generated value and apply them to your x coordinates and y coordinates as applicable. The result would be a grid of similarly constrained(no larger than the grid cell), but randomly shaped, Polygons.
EDIT:
Taking another look and fooling around a bit, I took the general concept as I described above and made a stab at an implementation:
public void paintComponent(Graphics g) {
int[] xCoord = new int[3];
int[] yCoord = new int[3];
int colCnt = 5;
int rowCnt = 2;
int maxCellWidth = getWidth() / colCnt;
int maxCellHeight = getHeight() / rowCnt;
for (int i = 0; i < (colCnt * rowCnt); i++) {
int xMultiple = i % colCnt;
int yMultiple = i / colCnt;
for (int j = 0; j < 3; j++) {
xCoord[j] = generator.nextInt(maxCellWidth)
+ (maxCellWidth * xMultiple);
yCoord[j] = generator.nextInt(maxCellHeight)
+ (maxCellHeight * yMultiple);
}
triangles.add(new Polygon(xCoord, yCoord, 3));
}
//... the rest of your method
}
As you can see, all of the Polygons have all points randomly generated, as opposed to your method of generating the first point and then making the rest relative to the first. There is a sense of randomness that is lost, however, as the Polygons are laid out in a grid-like pattern.
Create Area objects from your new polygon as well as for all existing polygons.
Subtract the new polygon's area from the existing ones. If the subtract changed the area, the polygons overlap.
Area newArea = new Area(newPolygon);
Area existingArea = new Area(existingPolygon);
Area existingAreaSub = new Area(existingPolygon); existingAreaSub.subtract(newArea);
boolean intersects = existingAreaSub.equals(existingArea);
You could implement a method Polycon.containsPoint( x, y ) and repeat your random generation until this method returns false for all drawn Polygons.
I have achieved this in Android Using Kotlin (See github project) by using JTS see here
Step-1:
Add JTS library to your project
implementation group: 'org.locationtech.jts', name: 'jts-core', version: '1.15.0'
Step-2:
Create JTS polygon objects for both polygon
// create polygons One
var polygoneOneArray: ArrayList<Coordinate> = ArrayList()
for (points in polygonOnePointsList) {
polygoneOneArray.add(Coordinate(points.latitude(), points.longitude()))
}
val polygonOne: org.locationtech.jts.geom.Polygon = GeometryFactory().createPolygon(
polygoneOneArray.toTypedArray()
)
// create polygons Two
var polygoneTwoArray: ArrayList<Coordinate> = ArrayList()
for (points in polygoneTwoPointsList) {
polygoneTwoArray.add(Coordinate(points.latitude(), points.longitude()))
}
val polygonTwo: org.locationtech.jts.geom.Polygon = GeometryFactory().createPolygon(
polygoneTwo.toTypedArray()
)
Step-3:
Get Common Area of both Polygon
val intersection: org.locationtech.jts.geom.Geometry = polygonOne.intersection(polygonTwo)
Step-4:
Remove common Area from polygonTwo
val difference: org.locationtech.jts.geom.Geometry = polygonTwo.difference(intersection)
Step-5:
Merge Both polygonOne and update polygonTwo
val union: org.locationtech.jts.geom.Geometry = mergePolygonList.get(0).polygons.union(difference)
Step-5:
Now pick points from Geometry and draw a final merged Polygon
val array: ArrayList<Coordinate> = union.coordinates.toList() as ArrayList<Coordinate>
val pointList: ArrayList<Point> = ArrayList()
for (item in array) {
pointList.add(Point.fromLngLat(item.y, item.x))
}
var list: ArrayList<List<Point>> = ArrayList<List<Point>>()
list.add(pointList)
style.addSource(
GeoJsonSource(
"source-id${timeStamp}",
Feature.fromGeometry(Polygon.fromLngLats(list))
)
)