Thanks to Reading ESRI shapefiles from the InputStream in Java I can read my shapefiles and access every GeometryAttribute, but I also need to convert it coordinates in long/lat format, it might be 40°44′55″N, 73 59 11W or best 40.7486, -73.9864.
example of my WKT is
GeometryAttribute sourceGeometry = feature.getDefaultGeometryProperty();
CoordinateReferenceSystem example = sourceGeometry.getDescriptor().getCoordinateReferenceSystem();
String wkt = example.toWKT();
PROJCS["ETRS_1989_Poland_CS92",
GEOGCS["GCS_ETRS_1989",
DATUM["D_ETRS_1989",
SPHEROID["GRS_1980", 6378137.0, 298.257222101]],
PRIMEM["Greenwich", 0.0],
UNIT["degree", 0.017453292519943295],
AXIS["Longitude", EAST],
AXIS["Latitude", NORTH]],
PROJECTION["Transverse_Mercator"],
PARAMETER["central_meridian", 19.0],
PARAMETER["latitude_of_origin", 0.0],
PARAMETER["scale_factor", 0.9993],
PARAMETER["false_easting", 500000.0],
PARAMETER["false_northing", -5300000.0],
UNIT["m", 1.0],
AXIS["x", EAST],
AXIS["y", NORTH]]
GeoTools has a number of ways to reproject your geometries depending on what you want to do after your reproject them.
The simplest is to use a ReprojectingFeatureCollection to provide you with a new collection in your required projection (in this case EPSG:4326) or you can create a JTS.transform and use that on individual geometries.
ReprojectingFeatureCollection rfc = new ReprojectingFeatureCollection(features, CRS.decode("epsg:4326"));
or
CoordinateReferenceSystem source = sourceGeometry.getDescriptor().getCoordinateReferenceSystem();
CoordinateReferenceSystem target = CRS.decode("epsg:4326");
MathTransform transform = CRS.findMathTransform(source, target, lenient);
Geometry geometry2 = JTS.transform(geometry, transform);
Printing the coordinates of those new geometries will give you decimal degrees (3.234545) if you need DMS (1°3'3") then a class like this will help:
public class DMSToDegrees {
static public double convert(int degrees, int minutes, double seconds) {
//to allow for negative (i.e. W or S) values note the sign of the degrees
float sign = Math.signum(degrees);
if(sign==0.0) {
//we'll consider 0 to be positive
sign = 1.0f;
}
//seconds are 1/60th of a minute so express as a fractional minute
double dmins = minutes+seconds/60.0;
//minutes are 1/60th of a degree so express as a fractional degree
double deg = Math.abs(degrees) + dmins/60.0;
// put the sign back on the result
return sign*deg;
}
static public double[] reverse(double degrees){
//to allow for negative (i.e. W or S) values note the sign of the degrees
double sign = Math.signum(degrees);
if(sign==0.0) {
//we'll consider 0 to be positive
sign = 1.0f;
}
double[] ret = new double[3];
degrees = Math.abs(degrees);
ret[0] = Math.floor(degrees);
double mins = degrees - ret[0];
ret[1] = Math.floor(mins*60);
ret[2] = ((mins*60 - ret[1]))*60;
ret[0]*=sign;
return ret;
}
}
Related
I'm quite confused about distance calculations.
I'm using this website as a reference:
https://www.omnicalculator.com/other/latitude-longitude-distance
Then I got an implementation of a distance calculation (haversine) from here:
https://tutorialspoint.dev/algorithm/geometric-algorithms/program-distance-two-points-earth
And I want to compare this with various different implementations from Spatial4J.
I'm using these coordinates to test with:
Point 1: 40.688939, -74.04455
Point 2: 40.746853, -73.985633
And I'm getting pretty big differences between different ways of calculating the distance between these two points.
First, what mainly concerns me is that the website (omnicalculator) and the implementation from tutorialspoint agree completely on the distance: 8.132 km
But none of my Spatial4J calculations agree with that number. The one that comes closest to it is the CartesianDistCalc implementation at 8.262 km. The tutorialspoint demo code claims to be using haversine but the output of Spatial4J haversine DistCalc implementation is quite a ways off at 7.313 km.
But can somebody explain to me where these differences are coming from and what the "correct" one is?
Below is my experimental code:
import org.junit.jupiter.api.Test;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.distance.CartesianDistCalc;
import org.locationtech.spatial4j.distance.GeodesicSphereDistCalc;
class GeodesicCalculationTest {
#Test
void testGeodesicCalculations(){
SpatialContext ctx = SpatialContext.GEO;
var startPoint = ctx.getShapeFactory().pointLatLon(40.688939, -74.04455);
var endPoint = ctx.getShapeFactory().pointLatLon(40.746853, -73.985633);
System.out.println("GEO spatial context: " + ctx.calcDistance(startPoint, endPoint) * 100);
System.out.println("Haversine: " + new GeodesicSphereDistCalc.Haversine().distance(startPoint, endPoint) * 100);
System.out.println("Law of cosine: " + new GeodesicSphereDistCalc.LawOfCosines().distance(startPoint, endPoint) * 100);
System.out.println("Vincenty: " + new GeodesicSphereDistCalc.Vincenty().distance(startPoint, endPoint) * 100);
System.out.println("Cartesian: " + new CartesianDistCalc().distance(startPoint, endPoint) * 100);
System.out.println("Tutorials Point (haversine): " + distance(startPoint.getLat(), endPoint.getLat(), startPoint.getLon(), endPoint.getLon()));
}
public static double distance(double lat1, double lat2, double lon1, double lon2) {
// The math module contains a function
// named toRadians which converts from
// degrees to radians.
lon1 = Math.toRadians(lon1);
lon2 = Math.toRadians(lon2);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
// Haversine formula
double dlon = lon2 - lon1;
double dlat = lat2 - lat1;
double a = Math.pow(Math.sin(dlat / 2), 2)
+ Math.cos(lat1) * Math.cos(lat2)
* Math.pow(Math.sin(dlon / 2),2);
double c = 2 * Math.asin(Math.sqrt(a));
// Radius of earth in kilometers. Use 3956
// for miles
double r = 6371;
// calculate the result
return(c * r);
}
}
And the output of running it:
GEO spatial context: 7.31307025220976
Haversine: 7.31307025220976
Law of cosine: 7.313070251733588
Vincenty: 7.3130702522095286
Cartesian: 8.261503667613857
Tutorials Point (haversine): 8.131763102409689
I'm multiplying the Spatial4J calculations by 100 which is also confusing to me... it doesn't really make sense that Spatial4J is giving me answers as 1/100th of a kilometer???
I realise I must be doing something wrong or completely misunderstanding some premises here. I would really appreciate some help in understanding what that is.
The result of SpatialContext.calcDistance(Point p, Point p2) is in degrees. To convert those degrees to km you need to multiply it by the constant DistanceUtils.DEG_TO_KM
SpatialContext ctx = SpatialContext.GEO;
var startPoint = ctx.getShapeFactory().pointLatLon(40.688939, -74.04455);
var endPoint = ctx.getShapeFactory().pointLatLon(40.746853, -73.985633);
double distanceInDegrees = ctx.calcDistance(startPoint, endPoint);
double distanceInKm = distanceInDegrees * DistanceUtils.DEG_TO_KM;
System.out.println("GEO spatial context: " + distanceInKm);
This gives you the output:
GEO spatial context: 8.131774297975046
Which is very close to your example from
Tutorials Point (haversine): 8.131763102409689
The difference is because Spatial4j is using the value 6371.0087714 for the radius of the earth in km, where as in your example you are using 6371.
First I'm a newbie in GPS system.
I have GPS coordinates in WGS-84 receive from a basic GPS in USB.
I want to calculate the distance beetween this two point.
But I want the plane distances. So I have first to convert this coordinates to an other CRS example "EPSG:2154" for Lambert 93. And after calulate the distance.
I try to use Geotools but the examples in the docs are not releveant for me and I d'ont understand how to do this.
I thought first I have to found the matching transform like this :
DefaultGeographicCRS crs = DefaultGeographicCRS.WGS84;
//EPSG:2154 RGF93 / Lambert-93 (Google it)
CoordinateReferenceSystem crs2 = CRS.decode("EPSG:2154");
MathTransform transform = CRS.findMathTransform(crs, crs2);
But after reading docs it seems the transformation works for x,y coordinates not lat/long. And i do not understand how to use the MathTransform as it doesn't accept point with lat/long. I also try the example below but executing the code doesn't give the same results for me.
Calculating distance between two points, using latitude longitude?
So if anyone with good knowledge in GPS and Geotools is able to help me.
Thanks
If you simply want the distance between two GPS points then you can use the GeodeticCalculator to calculate this in metres (and the Units library to convert it to any distance unit you like:
import javax.measure.MetricPrefix;
import javax.measure.Quantity;
import javax.measure.quantity.Length;
import org.geotools.referencing.CRS;
import org.geotools.referencing.CRS.AxisOrder;
import org.geotools.referencing.GeodeticCalculator;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import si.uom.SI;
import systems.uom.common.USCustomary;
import tech.units.indriya.quantity.Quantities;
public class OrthodromicDistance2 {
/**
* take two pairs of lat/long and return bearing and distance.
*
* #param args
*/
public static void main(String[] args) {
DefaultGeographicCRS crs = DefaultGeographicCRS.WGS84;
if (args.length != 4) {
System.err.println("Need 4 numbers lat_1 lon_1 lat_2 lon_2");
return;
}
GeometryFactory geomFactory = new GeometryFactory();
Point[] points = new Point[2];
for (int i = 0, k = 0; i < 2; i++, k += 2) {
double x = Double.parseDouble(args[k]);
double y = Double.parseDouble(args[k + 1]);
if (CRS.getAxisOrder(crs).equals(AxisOrder.NORTH_EAST)) {
System.out.println("working with a lat/lon crs");
points[i] = geomFactory.createPoint(new Coordinate(x, y));
} else {
System.out.println("working with a lon/lat crs");
points[i] = geomFactory.createPoint(new Coordinate(y, x));
}
}
System.out.println(points[0]);
System.out.println(points[1]);
double distance = 0.0;
GeodeticCalculator calc = new GeodeticCalculator(crs);
calc.setStartingGeographicPoint(points[0].getX(), points[0].getY());
calc.setDestinationGeographicPoint(points[1].getX(), points[1].getY());
distance = calc.getOrthodromicDistance();
double bearing = calc.getAzimuth();
Quantity<Length> dist = Quantities.getQuantity(distance, SI.METRE);
System.out.println(dist.to(MetricPrefix.KILO(SI.METRE)).getValue() + " Km");
System.out.println(dist.to(USCustomary.MILE).getValue() + " miles");
System.out.println("Bearing " + bearing + " degrees");
}
}
This will work for any points on the globe no matter how far apart they are and makes use of GeographicLib by Charles F. F. Karney and gives an accuracy of nanometres.
If however, you want to carry out more geometry operations on your points/lines etc then you are right to want to transform your points to a projected CRS (such as Lambert 93):
CoordinateReferenceSystem wgs84= CRS.decode("EPSG:4326", true);
CoordinateReferenceSystem lambert = CRS.decode("EPSG:2154", true);
MathTransform toMeters= CRS.findMathTransform(wgs84, lambert);
Geometry output1 = JTS.transform(input1, toMeters);
Geometry output2 = JTS.transform(input2, toMeters);
double distance = output1.distance(output2);
I've tried to create a basic NN using the book
"Make Your Own Neural Network" by Tariq Rashid
and using the coding train videos:
https://www.youtube.com/watch?v=XJ7HLz9VYz0&list=PLRqwX-V7Uu6aCibgK1PTWWu9by6XFdCfh
and the nn.js class on the coding train git as a reference
https://github.com/shiffman/Neural-Network-p5/blob/master/nn.js
I writing the NN network in java, and I tried just like in the playlist to train the network on XOR after I succeeded in doing a single perceptron.
but for some reason, even though my code is similar to what the book is doing and same in the videos (except in the videos he using JS).
when I train the network for around 500000 times with randomized data set of XOR inputs (total of 4 input [1,0] [0,1] [0,0] [1,1]).
when I giving it to guess after the training the all the 4 options I get results closer to 0.5 than to 1,1,0,0 (the order of the inputs in the test are [1,0] [0,1] [0,0] [1,1])
this is my training function:
public void train(double [] inputs, double[] target) {
//generates the Hidden layer values
this.input = Matrix.fromArrayToMatrix(inputs);
feedForward(inputs);
//convert to matrices
Matrix targets = Matrix.fromArrayToMatrix(target);
//calculate the output error
Matrix outputErrors = Matrix.subtract(targets, output);
//calculate the Gradient
Matrix outputGradient = Matrix.map(output, NeuralNetwork::sigmoidDerivative);
outputGradient = Matrix.matrixMultiplication(outputGradient, outputErrors);
outputGradient.multiply(this.learningRate);
//adjust the output layer bias
this.bias_Output.add(outputGradient);
//calculate the hidden layer weights delta
Matrix hiddenT = Matrix.Transpose(hidden);
Matrix hiddenToOutputDelta = Matrix.matrixMultiplication(outputGradient, hiddenT);
//adjust the hidden layer weights
this.weightsHiddenToOutput.add(hiddenToOutputDelta);
//calculate the hidden layer error
Matrix weightsHiddenToOutputT = Matrix.Transpose(weightsHiddenToOutput);
Matrix hiddenErrors = Matrix.matrixMultiplication(weightsHiddenToOutputT, outputErrors);
//calculate the hidden gradient
Matrix hiddenGradient = Matrix.map(this.hidden, NeuralNetwork::sigmoidDerivative);
hiddenGradient = Matrix.matrixMultiplication(hiddenGradient, hiddenErrors);
hiddenGradient.multiply(this.learningRate);
//adjust the hidden layer bias
this.bias_Hidden.add(hiddenGradient);
//calculate the input layer weights delta
Matrix inputT = Matrix.Transpose(this.input);
Matrix inputToHiddenDelta = Matrix.matrixMultiplication(hiddenGradient, inputT);
//adjust the hidden layer weights
this.weightsInputToHidden.add(inputToHiddenDelta);
}
those are the sigmoid functions:
private static double sigmoid(double x) {
return 1d / (1d+ Math.exp(-x));
}
private static double sigmoidDerivative(double x) {
return (x * (1d - x));
}
I'm using this method to calculate the derivative because the network already getting the sigmoid function on the feed-forward process so all I do is calculate the derivative like that.
and this is my guess/ feedforward function:
public double[] feedForward(double [] inputs) {
double[] guess;
//generates the Hidden layer values
input = Matrix.fromArrayToMatrix(inputs);
hidden = Matrix.matrixMultiplication(weightsInputToHidden, input);
hidden.add(bias_Hidden);
//activation function
hidden.map(NeuralNetwork::sigmoid);
//Generates the output layer values
output = Matrix.matrixMultiplication(weightsHiddenToOutput, hidden);
output.add(bias_Output);
//activation function
output.map(NeuralNetwork::sigmoid);
guess = Matrix.fromMatrixToArray(output);
return guess;
}
this is in the main class the data set I'm giving him:
NeuralNetwork nn = new NeuralNetwork(2,2,1);
double [] label0 = {0};
double [] label1 = {1};
Literal l1 = new Literal(label1,0,1);
Literal l2 = new Literal(label1,1,0);
Literal l3 = new Literal(label0,0,0);
Literal l4 = new Literal(label0,1,1);
Literal[] arr = {l1, l2, l3, l4};
Random random = new Random();
for(int i = 0 ; i<500000 ; i++) {
Literal l = arr[i%4];
nn.train(l.getTruthValue(), l.getLabel());
}
System.out.println(Arrays.toString(nn.feedForward(l1.getTruthValue())));
System.out.println(Arrays.toString(nn.feedForward(l2.getTruthValue())));
System.out.println(Arrays.toString(nn.feedForward(l3.getTruthValue())));
System.out.println(Arrays.toString(nn.feedForward(l4.getTruthValue())));
but for some reason the outputs look like that:
[0.47935468493879807]
[0.5041956026507048]
[0.4575246472403595]
[0.5217568912941623]
I've tried changing it to subtract instead of add-on every bias and weights update (cause you need the negative gradient although both in the book and in the videos they use add instead of subtract) meaning changing those 4 lines to subtract:
this.bias_Output.subtract(outputGradient);
this.weightsHiddenToOutput.subtract(hiddenToOutputDelta);
this.bias_Hidden.subtract(hiddenGradient);
this.weightsInputToHidden.subtract(inputToHiddenDelta);
those are the 2 main outputs I get:
[0.9999779359460259]
[0.9999935716126019]
[0.9999860145346924]
[0.999990155468117]
or
[1.7489664881918983E-5]
[6.205315404676972E-6]
[8.41530873105465E-6]
[1.1853929628341918E-5]
I'm pretty sure the problem isn't in my Matrix class that I've created because I checked it before and all the add, subtract, multiply, transpose and it worked fine.
I would really appreciate if someone could look at this code and help me to figure out the problem
The BicubicSplineInterpolator is returning some curious results for my input set.
Here is my test case:
double[] xValues = new double[] {36, 36.001, 36.002};
double[] yValues = new double[] {-108.00, -107.999, -107.998};
double[][] fValues = new double[][] {{1915, 1906, 1931},
{1877, 1889, 1894},
{1878, 1873, 1888}};
BicubicSplineInterpolator interpolator = new BicubicSplineInterpolator();
BicubicSplineInterpolatingFunction interpolatorFunction = interpolator.interpolate(xValues, yValues, fValues);
double[][] results = new double[9][9];
double x = 36;
int arrayIndexX = 0;
int arrayIndexY = 0;
while(x <= 36.002)
{
double y = -108;
arrayIndexY = 0;
while (y <= -107.998)
{
results[arrayIndexX][arrayIndexY] = interpolatorFunction.value(x, y);
System.out.println(results[arrayIndexX][arrayIndexY]);
y = y + 0.00025;
arrayIndexY++;
}
x = x + 0.00025;
arrayIndexX++;
}
After running this snippet of code, the interpolated values contained within the results array are:
1915.0
-3938.5937499822526
-1760.2500002294219
2246.2187497695777
1877.000000525819
250.9999999288558
1803.7499996906008
3403.374999905478
1889.0000007034323
-922.343750031719
390070.8886686283
320411.8593862744
91169.82228340462
3414.031240516051
140099.0224580196
124712.34376105569
48068.829113991116
2932.7499997298
-1277.0000000323469
335413.0390564674
264381.1250073778
61474.21095159976
2539.249988033902
335702.3671824192
264764.37503049
61763.88284085272
2547.749982131645
-37.90625000258933
112126.77147883564
76170.70312516135
2453.8925818554126
1336.3437417931855
362677.29393607465
272636.7187811567
46134.229521767236
1834.6249738819897
1877.0000000976995
-1228.312492238307
-1778.749983159687
-501.0624825709448
1877.9999996234117
304.4687496629192
1787.2500015275245
3316.9062529374487
1873.0000007069889
3414.031249990962
153858.71874489737
320991.32811795553
328540.929697798
236.59381305763964
49250.68456339003
124800.53124625524
139093.54200382315
1640.9687914999472
2539.249999955474
140423.82030525914
265019.87498830666
257740.9296891929
0.5000480143353343
140431.7734211699
265401.6249928146
258308.9765831194
5.500072199653914
1336.343749981772
56546.050777358614
76540.60936913849
58774.425778594334
701.9062589909881
161169.991191242
273494.90623999
249357.90724363495
-692.468683006271
For a set of f values that are between ~1800 and ~2000 as defined above, I'm not sure why there are negative values in the interpolation set. Additionally there values that are much greater than the largest value in the input set, such as 257740.9296891929 and 249357.90724363495.
I set up this input set in MatLab to compare my results using the interp2 cubic method and the results from MatLab are much more along the lines of what I would have expected. Here are the results for the same input set in MatLab:
1915
1901.84375000034
1891.12500000000
1882.84375000020
1877
1873.59375000003
1872.62499999999
1874.09375000004
1878
1909.56249999997
1900.16796875024
1892.21875000001
1885.71484375018
1880.65625000002
1877.04296875006
1874.87500000006
1874.15234375000
1874.87499999998
1906.24999999997
1899.57812500018
1893.62500000002
1888.39062500018
1883.87500000004
1880.07812500009
1877.00000000011
1874.64062499998
1872.99999999998
1905.06250000000
1900.07421875013
1895.34374999999
1890.87109375011
1886.65624999998
1882.69921875004
1879.00000000009
1875.55859374994
1872.37500000000
1906.00000000006
1901.65625000018
1897.37500000006
1893.15625000018
1889.00000000006
1884.90625000011
1880.87500000017
1876.90624999999
1873.00000000004
1909.06250000012
1904.32421875022
1899.71875000007
1895.24609375018
1890.90625000005
1886.69921875010
1882.62500000016
1878.68359375000
1874.87500000007
1914.25000000000
1908.07812500017
1902.37500000000
1897.14062500014
1892.37500000000
1888.07812500006
1884.25000000010
1880.89062499996
1878
1921.56250000000
1912.91796875023
1905.34375000000
1898.83984375017
1893.40625000000
1889.04296875005
1885.75000000008
1883.52734374998
1882.37500000000
1931
1918.84375000032
1908.62500000000
1900.34375000021
1894
1889.59375000005
1887.12500000004
1886.59375000001
1888
One other point of note. When the number of decimal points are reduced from 3 to 2 and 2 to 1 for the x and y values (such as 36.01 or 36.1), the interpolated results gravitate toward the "expected" realm (1800-2000). The negative numbers and extremely large numbers begin to disappear.
I am using version 3.3 of the commons math library.
Any insight as to why these values are being interpolated as such would be greatly appreciated. Thank you.
Let's say that I am collecting users location data every 20 minutes. At the end of the day I have an ArrayList of objects that contain lat and long fields and other data.
I have two problems that I am facing and trying to figure out:
Some of the locations are taken from inside of a building so they are not very accurate and could be spread around the actual location where the user was at the time.
Some of the locations are taken at different times but from the same location, as the user didn't moved.
What I want to achieve is to find all the locations that are near one another: lets say 70 meters, find the average location of all those locations and replace them only with this one average location.
So I am coming to the two important questions:
What would be the best way to find all near locations < 70 meter distance (Take in mind that the array contains valid changes in location. So I have to find the groups of near ones and leave the others intact).
Is there a method or a way to find the average location of many near ones?
Regarding near positions I previously answered a similar question here: Android Maps v2 - animate camera to include most markers
Specifically I think you would be able to use this piece of code:
private List<Marker> getSurroundingMarkers(List<Marker> markers,
LatLng origin, int maxDistanceMeters) {
List<Marker> surroundingMarkers = surroundingMarkers = new ArrayList<Marker>();
if (markers == null) return surroundingMarkers ;
for (Marker marker : markers) {
double dist = distBetween(origin, marker.getPosition());
if (dist < maxDistanceMeters) {
surroundingMarkers.add(marker);
}
}
return surroundingMarkers;
}
private float distBetween(LatLng pos1, LatLng pos2) {
return distBetween(pos1.latitude, pos1.longitude, pos2.latitude,
pos2.longitude);
}
/** distance in meters **/
private float distBetween(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2)
* Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = earthRadius * c;
int meterConversion = 1609;
return (float) (dist * meterConversion);
}
Possibly rewriting the Marker part to use LatLng instead.
regarding the averaging, it should be a simple matter of (say you have n LatLng's):
lat_avg = (lat1+lat2+...+latn)/n
lng_avg = (lng1+lng2+...+lngn)/n
latlng_avg = new LatLng(lat_avg, lat_lng)
I' not sure how you're getting the user's location - whether your using a traditional LocationManager or play services. I've always modeled my location getting on this approach documented on the android developers blog. If you're flexible in switching between location gathering methods, whether the person is inside or outside should not matter that much. You should be getting the best possible location at any given time.
Assuming you're getting locations on a sufficient time schedule (I don't know when you're checking for updates but since you want everything inside a 70m radius I'm assuming its on a time schedule and not distance change) the basic way to find the average point is:
(1) Convert each lat/long pair into a unit-length 3D vector.
(2) Sum each of those vectors
(3) Normalise the resulting vector
(4) Convert back to spherical coordinates
That approach is documented here as well as in a much earlier SO post on calculating the average of a set of angles
The example code is pretty easy to follow - just plug in the lat long values you get from your location grab and you should be ok.
Well for markers that come from the same location I have created the following method:
public ArrayList<MyLocation> removeSameLocationMarkers(List<ParseObject> objects, int maxDistanceMeters)
{
boolean isLocationExist;
ArrayList<MyLocation> acceptedLocations = new ArrayList<MyLocation>();
if (objects == null) return acceptedLocations;
for (ParseObject location1 : objects)
{
isLocationExist = false;
for (MyLocation location2 : acceptedLocations)
{
if (!location1.equals(location2))
{
float distance = distBetween(location1.getDouble("latitude"), location1.getDouble("longitude"), location2.getLatitude(), location2.getLongitude());
if (distance < maxDistanceMeters)
{
location2.addTimeToLocation(location1.getString("time"));
isLocationExist = true;
}
}
}
if (!isLocationExist)
{
Location newLocation = new Location("");
newLocation.setLatitude(location1.getDouble("latitude"));
newLocation.setLongitude(location1.getDouble("longitude"));
String provider = location1.getString("provider");
if (provider != null)
{
newLocation.setProvider(provider);
}
MyLocation newMyLocation = new MyLocation(newLocation);
newMyLocation.addTimeToLocation(location1.getString("time"));
acceptedLocations.add(newMyLocation);
}
}
return acceptedLocations;
}