我正在尝试将世界坐标转换为像素坐标。问题是,有些文件(shapefile)不能正常转换。线条倾斜或移动,它们看起来应该与我加载文件时完全一样。
我转换线条的原因是因为它需要在Adobe Illustrator中显示,并且法线贴图要大得多以便正确显示。
有更好的方法可以更可靠地将世界坐标转换为屏幕坐标吗? (convertLines方法是发生所有转换的地方)
ArrayList<FeatureLine> temp = new ArrayList();
public static void main(String[] args) throws Exception {
MCV_TestProgram test = new MCV_TestProgram();
}
public MCV_TestProgram() {
temp.add(new FeatureLine("2466308.97 709571.48, 2466306.03 709566.79", 0));
temp.add(new FeatureLine("2466800.14 710357.15, 2466308.97 709571.48", 1));
temp.add(new FeatureLine("2456506.25 707356.2, 2456487.75 707715.23, 2456450.68 707809.01", 2));
temp.add(new FeatureLine("2324352.2 669626.61, 2324365.6 669328.81, 2324146.77 669316.22, 2324165.41 669264.1, 2324174.26 669057.93, 2324192.39 668895.68, 2324211.04 668561.95, 2324219.11 668494.04, 2324230.7 668370.9, 2324247.66 668128.16, 2324260.89 667951.94, 2324268.86 667848.91, 2324278.83 667705.33, 2324289.97 667508.67", 3));
convertLines(temp);
}
// Converts map lines to fit in smaller window (mainly for Adobe Illustrator)
private ArrayList<FeatureLine> convertLines(ArrayList<FeatureLine> lines) {
ArrayList<FeatureLine> convertedCoords = new ArrayList();
try {
Rectangle imageBounds = new Rectangle(250, 200, 1000, 800);
CoordinateReferenceSystem crs = createCRS();
ReferencedEnvelope mapBounds = new ReferencedEnvelope(2104208.77, 2595754.33, 500627.08, 1286916.23, crs);
AffineTransform world2screen = createTransform(mapBounds, imageBounds);
for (FeatureLine coord : lines) {
Point2D screenCoordStart = world2screen.transform(coord.StartPoint, null);
Point2D screenCoordEnd = world2screen.transform(coord.EndPoint, null);
if (coord.StartPoint.x != 0.0) {
convertedCoords.add(new FeatureLine(screenCoordStart, screenCoordEnd));
}
}
} catch (FactoryException | MismatchedDimensionException ex) {
Logger.getLogger(MCV_TestProgram.class.getSimpleName()).log(Level.SEVERE, "Error occured while converting lines", ex);
}
return convertedCoords;
}
// Custom line class to store line data, StartPoint and Endpoint (coordinates)
// of one unbreaking line.
public class FeatureLine {
private Point2D.Double StartPoint = new Point2D.Double();
private Point2D.Double EndPoint = new Point2D.Double();
public FeatureLine(double x1, double y1, double x2, double y2) {
StartPoint.x = x1;
StartPoint.y = y1;
EndPoint.x = x2;
EndPoint.y = y2;
}
public FeatureLine(Point2D.Double start, Point2D.Double end) {
StartPoint = start;
EndPoint = end;
}
public FeatureLine(Point2D start, Point2D end) {
StartPoint = (Point2D.Double) start;
EndPoint = (Point2D.Double) end;
}
public FeatureLine(String parseString, int index) {
String latlon[];
String xy1[];
String xy2[];
double x1, y1;
double x2, y2;
try {
if (!parseString.equals("")) {
latlon = parseString.split(",");
xy1 = latlon[0].split(" ");
xy2 = latlon[1].replaceFirst(" ", "").split(" ");
x1 = Double.parseDouble(xy1[0]);
y1 = Double.parseDouble(xy1[1]);
x2 = Double.parseDouble(xy2[0]);
y2 = Double.parseDouble(xy2[1]);
StartPoint.x = x1;
StartPoint.y = y1;
EndPoint.x = x2;
EndPoint.y = y2;
}
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error occured while creating line at: " + index + " ", ex);
}
}
public double getX(int index) {
if (index == 0) {
return StartPoint.x;
} else {
return EndPoint.x;
}
}
public double getY(int index) {
if (index == 0) {
return StartPoint.y;
} else {
return EndPoint.y;
}
}
public void setX(double x, int index) {
if (index == 0) {
StartPoint.x = x;
} else {
EndPoint.x = x;
}
}
public void setY(double y, int index) {
if (index == 0) {
StartPoint.y = y;
} else {
EndPoint.y = y;
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
return (builder.append(String.valueOf(StartPoint.x)).append(" ").append(String.valueOf(StartPoint.y)).append(", ")
.append(String.valueOf(EndPoint.x)).append(" ").append(String.valueOf(EndPoint.y))).toString();
}
}
/**
* Uses the window's aspect ratio to choose a scale factor for the map,
* and constructs an AffineTransform to scale the shapefile's contents.
*/
private AffineTransform createTransform(ReferencedEnvelope mapEnvelope, Rectangle imageBounds) {
double mapWidth = mapEnvelope.getWidth();
double mapHeight = mapEnvelope.getHeight();
double imageWidth = imageBounds.getWidth();
double imageHeight = imageBounds.getHeight();
double sx = imageWidth / mapWidth;
double sy = imageHeight / mapHeight;
double aspectRatio = mapWidth / mapHeight;
double scale = aspectRatio < 1 ? sy : sx;
AffineTransform m = new AffineTransform();
m.scale(scale, scale);
return m;
}
// Create CRS from custom data
private CoordinateReferenceSystem createCRS() throws FactoryException {
String wkt = "PROJCS[\"NAD_1983_Michigan_GeoRef_Feet_US\"," +
"GEOGCS[\"GCS_North_American_1983\"," +
"DATUM[\"D_North_American_1983\"," +
"SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]]," +
"PRIMEM[\"Greenwich\", 0.0]," +
"UNIT[\"degree\", 0.017453292519943295]," +
"AXIS[\"Longitude\", EAST]," +
"AXIS[\"Latitude\", NORTH]]," +
"PROJECTION[\"Hotine_Oblique_Mercator\"]," +
"PARAMETER[\"longitude_of_center\", -86.0]," +
"PARAMETER[\"latitude_of_center\", 45.30916666666666]," +
"PARAMETER[\"azimuth\", 337.25555555555593]," +
"PARAMETER[\"scale_factor\", 0.9996]," +
"PARAMETER[\"false_easting\", 8355401.583000001]," +
"PARAMETER[\"false_northing\", -14284780.538]," +
"PARAMETER[\"rectified_grid_angle\", 337.25555555555593]," +
"UNIT[\"foot_survey_us\", 0.3048006096012192]," +
"AXIS[\"X\", EAST]," +
"AXIS[\"Y\", NORTH]]";
CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null);
CoordinateReferenceSystem crs = crsFactory.createFromWKT(wkt);
return crs;
}