]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/map/MapUtils.java
Version 19.2, December 2018
[GpsPrune.git] / tim / prune / gui / map / MapUtils.java
1 package tim.prune.gui.map;
2
3 import java.awt.Color;
4 import java.awt.image.BufferedImage;
5
6 /**
7  * Class to manage coordinate conversions and other stuff for maps
8  */
9 public abstract class MapUtils
10 {
11         /**
12          * Transform a longitude into an x coordinate
13          * @param inLon longitude in degrees
14          * @return scaled X value from 0 to 1
15          */
16         public static double getXFromLongitude(double inLon)
17         {
18                 return (inLon + 180.0) / 360.0;
19         }
20
21         /**
22          * Transform a latitude into a y coordinate
23          * @param inLat latitude in degrees
24          * @return scaled Y value from 0 to 1
25          */
26         public static double getYFromLatitude(double inLat)
27         {
28                 return (1 - Math.log(Math.tan(inLat * Math.PI / 180) + 1 / Math.cos(inLat * Math.PI / 180)) / Math.PI) / 2;
29         }
30
31         /**
32          * Transform an x coordinate into a longitude
33          * @param inX scaled X value from 0(-180deg) to 1(+180deg)
34          * @return longitude in degrees
35          */
36         public static double getLongitudeFromX(double inX)
37         {
38                 // Ensure x is really between 0 and 1 (to wrap longitudes)
39                 double x = ((inX % 1.0) + 1.0) % 1.0;
40                 // Note: First %1.0 restricts range to (-1,1), then +1.0 shifts to (0,2)
41                 // Finally, %1.0 to give (0,1)
42                 return x * 360.0 - 180.0;
43         }
44
45         /**
46          * Transform a y coordinate into a latitude
47          * @param inY scaled Y value from 0 to 1
48          * @return latitude in degrees
49          */
50         public static double getLatitudeFromY(double inY)
51         {
52                 double n = Math.PI * (1 - 2 * inY);
53                 return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
54         }
55
56         /**
57          * Tests whether there are any dark pixels in the image within the specified x,y rectangle
58          * @param inImage image to test
59          * @param inX left X coordinate
60          * @param inY bottom Y coordinate
61          * @param inWidth width of rectangle
62          * @param inHeight height of rectangle
63          * @param inTextColour colour of text
64          * @return true if the rectangle overlaps stuff too close to the given colour
65          */
66         public static boolean overlapsPoints(BufferedImage inImage, int inX, int inY,
67                 int inWidth, int inHeight, Color inTextColour)
68         {
69                 // each of the colour channels must be further away than this to count as empty
70                 final int BRIGHTNESS_LIMIT = 80;
71                 final int textRGB = inTextColour.getRGB();
72                 final int textLow = textRGB & 255;
73                 final int textMid = (textRGB >> 8) & 255;
74                 final int textHigh = (textRGB >> 16) & 255;
75                 try
76                 {
77                         // loop over x coordinate of rectangle
78                         for (int x=0; x<inWidth; x++)
79                         {
80                                 // loop over y coordinate of rectangle
81                                 for (int y=0; y<inHeight; y++)
82                                 {
83                                         int pixelColor = inImage.getRGB(inX + x, inY - y);
84                                         // split into four components rgba
85                                         int pixLow = pixelColor & 255;
86                                         int pixMid = (pixelColor >> 8) & 255;
87                                         int pixHigh = (pixelColor >> 16) & 255;
88                                         //int fourthBit = (pixelColor >> 24) & 255; // alpha ignored
89                                         // If colours are too close in any channel then it's an overlap
90                                         if (Math.abs(pixLow-textLow) < BRIGHTNESS_LIMIT ||
91                                                 Math.abs(pixMid-textMid) < BRIGHTNESS_LIMIT ||
92                                                 Math.abs(pixHigh-textHigh) < BRIGHTNESS_LIMIT) {return true;}
93                                 }
94                         }
95                 }
96                 catch (NullPointerException e) {
97                         // ignore null pointers, just return false
98                 }
99                 return false;
100         }
101 }