/** * Checks that a transformation produces the expected result * * @param x the input pt x * @param y the input pt y * @param trans the transformation * @param xp the expected output x * @param yp the expected output y */ void checkTransformation(double x, double y, AffineTransformation trans, double xp, double yp) { Coordinate p = new Coordinate(x, y); Coordinate p2 = new Coordinate(); trans.transform(p, p2); assertEquals(xp, p2.x, .00005); assertEquals(yp, p2.y, .00005); // if the transformation is invertible, test the inverse try { AffineTransformation invTrans = trans.getInverse(); Coordinate pInv = new Coordinate(); invTrans.transform(p2, pInv); assertEquals(x, pInv.x, .00005); assertEquals(y, pInv.y, .00005); double det = trans.getDeterminant(); double detInv = invTrans.getDeterminant(); assertEquals(det, 1.0 / detInv, .00005); } catch (NoninvertibleTransformationException ex) { } }
/** * Create device locations in a path near the main zone. * * @param assignment * @param start * @return * @throws SiteWhereException */ protected List<IDeviceLocation> createDeviceLocations(IDeviceAssignment assignment, Date date) throws SiteWhereException { long current = date.getTime(); Polygon zone = GeoUtils.createPolygonForLocations(zoneLocations); Point centroid = zone.getCentroid(); // Calculate length of steps between locations based on bounding circle. MinimumBoundingCircle circle = new MinimumBoundingCircle(zone); double step = circle.getRadius() / 10; double cx = centroid.getX(); double cy = centroid.getY(); double deltaX = (Math.sqrt(Math.random()) * step * 2) - step; double deltaY = (Math.sqrt(Math.random()) * step * 2) - step; // Used to rotate deltas to turn path and stay inside polygon. AffineTransformation xform = new AffineTransformation(); xform.rotate(Math.toRadians(22.5)); List<IDeviceLocation> results = new ArrayList<IDeviceLocation>(); GeometryFactory factory = new GeometryFactory(); for (int x = 0; x < LOCATIONS_PER_ASSIGNMENT; x++) { boolean foundNext = false; // Add a little randomness to path. double waver = ((Math.random() * 20) - 10.0); AffineTransformation waverXform = new AffineTransformation(); waverXform.rotate(Math.toRadians(waver)); Coordinate waverDelta = new Coordinate(deltaX, deltaY); waverXform.transform(waverDelta, waverDelta); deltaX = waverDelta.x; deltaY = waverDelta.y; while (!foundNext) { Coordinate start = new Coordinate(cx, cy); Coordinate end = new Coordinate(cx + deltaX, cy + deltaY); Coordinate[] lineCoords = {start, end}; LineString line = factory.createLineString(lineCoords); if (zone.contains(line)) { DeviceLocationCreateRequest request = new DeviceLocationCreateRequest(); request.setLatitude(end.y); request.setLongitude(end.x); request.setElevation(0.0); request.setEventDate(new Date(current)); IDeviceLocation created = getDeviceManagement().addDeviceLocation(assignment.getToken(), request); results.add(created); cx = cx + deltaX; cy = cy + deltaY; foundNext = true; } else { // Rotate deltas and try again. Coordinate delta = new Coordinate(deltaX, deltaY); xform.transform(delta, delta); deltaX = delta.x; deltaY = delta.y; } } current += 30000; } LOGGER.info(PREFIX_CREATE_EVENTS + " " + results.size() + " locations. "); return results; }