Opened 17 years ago
Last modified 13 years ago
#2031 new enhancement
Draw labels at angles relative to true geographic north regardless of projection.
Reported by: | Owned by: | sdlime | |
---|---|---|---|
Priority: | high | Milestone: | |
Component: | MapServer C Library | Version: | unspecified |
Severity: | minor | Keywords: | |
Cc: | dmorissette |
Description (last modified by )
As far as I can tell Mapserver lacks the ability to draw symbols or labels at angles relative to true geographic north regardless of the map projection being used. All angles are only relative to the top of the image in the image coordinate system, not the map coordinate system. Having the ability to draw symbols/labels relative to true north is essential for some applications. For example, drawing the symbol of a ship pointed in the actual direction the ship is going on a polar stereographic map. The following is a proposed enhancement to the Mapfile LABEL object to support this capability. (I assume it should be fairly straightforward to make the same enhancements to the Mapfile STYLE object.) A) Create a new boolean directive for "LABEL" called something like "ANGLETRUENORTH". When set to false or absent LABEL angles should be treated as before. However if "ANGLETRUENORTH TRUE" is present in LABEL then an angle specified via "ANGLE" or "LABELANGLEITEM" should be drawn at the angle relative to geographic north where angle is given in degrees clockwise from 0 at the top where 0 = North, 90 = East, 180 = South, 270 = West. (I found it necessary to reverse the direction of the drawing angle from counter-clockwise to clockwise since the standard for these types of applications is clockwise.) B) Create a subroutine to offset the angle correctly. The following code will do this. Probably the logical place to put this would be in mapproject.c?: ------------------------------begin code---------------------------------- /************************************************************************/ /* msProjectAngle() */ /* */ /* Shifts "angle" by the correct amount to keep it relative to the */ /* geographic north pole regardless of map projection and location */ /* on map. */ /* */ /* "angle" is relative to geographic north where angle is given in */ /* degrees clockwise from 0 at the top (0 = North, 90 = East, */ /* 180 = South, 270 = West). */ /* */ /* "mappoint" has been projected to the map projection and is the */ /* location of "angle" on map. */ /************************************************************************/ int msProjectAngle(mapObj *map, pointObj *mappoint, double *angle) { #ifdef USE_PROJ double angle_offset; pointObj mappoint2; /* Only transform angle if out proj is not latlong */ if(!pj_is_latlong(map->projection.proj)) { /* Make a copy of the first point */ mappoint2.x = mappoint->x; mappoint2.y = mappoint->y; /* convert to latlong */ if( msProjectPoint(&map->projection, &map->latlon, &mappoint2) == MS_FAILURE ) return MS_FAILURE; /* apply a slight offset(~100 meters) south of the original point */ mappoint2.y -= 3.0/(60.0*60.0); /* convert the offset point back to map projection */ if( msProjectPoint( &map->latlon, &map->projection, &mappoint2) == MS_FAILURE ) return MS_FAILURE; /* Calculate angle between these two points. This will be the angle offset relative to true north for the map projection. */ angle_offset = MS_RAD_TO_DEG*asin((mappoint->x - mappoint2.x)/sqrt(pow((mappoint->x - mappoint2.x),2.0) + pow((mappoint->y - mappoint2.y),2.0))); if((mappoint->y - mappoint2.y) < 0) angle_offset = 180 - angle_offset; *angle += angle_offset; } /* Change from counterclockwise to clockwise */ *angle = - *angle; return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectAngle()"); return(MS_FAILURE); #endif } -------------------------------end code----------------------------------- C) Modifiy mapdraw.c to include a call to the above subroutine where it draws the point labels if it detects the "ANGLETRUENORTH" directive. Attached is a proposed patch for mapdraw.c. Does the above seem like a reasonable approach? Would it be possible to include some variation of this in the next release? -Steve
Attachments (2)
Change History (13)
by , 17 years ago
Attachment: | mapdraw.c.patch added |
---|
by , 17 years ago
Attachment: | test_files.tar.gz added |
---|
A couple of map files and symbol fonts for testing
comment:2 by , 17 years ago
I like this enhancement idea, but would have a few questions/comments: 1- Instead of "ANGLETRUENORTH TRUE|FALSE", we could try to use something more generic and that could support other flags that apply to the angle in the future. For instance ANGLEMODE with a value of TRUENORTH. 2- The use of clockwise angles for this mode bugs me. I find that it's just going to lead to confusion if the default is counter-clockwise angles (as it is today) and TRUENORTH uses clockwise angles. Can you provide examples of "this type of applications" that use clockwise angles and justify this choice? For instance Geographic coordinate systems typically use (latitude, longitude), but we still use x,y (i.e. lon, lat) to refer to geographic coordinates to avoid causing confusion with axis order changing depending on the coordinate system. The WMS 1.3.0 spec has made that decision to break with the past and impose the use the "correct" axis order for every coordinate system and the mess that resulted (and still hasn't been resolved) is a good example of what happens when you trade simplicity for correctness. 3- If there is really a need to support clockwise angles then it's probably not limited to applications using TRUENORTH, and then perhaps we could use different values of ANGLEMODE to specify whether angles should be interpreted clockwise or counter-clockwise. Possible ANGLEMODE values: CCW (default), CW, TRUENORTHCCW, TRUENORTHCW
comment:3 by , 17 years ago
BTW, this enhancement probably needs a RFC before it can be integrated in MapServer.
comment:4 by , 17 years ago
I agree with Daniel with regard to the RFC, and I too am wondering if there are ways of generalizing this a bit.
comment:5 by , 17 years ago
In answer to Daniel's #4 comments I agree that changing from counter-clockwise to clockwise will cause confusion but I have no choice. In the world of marine navigation (which is the world I work in) heading, bearing, direction, course over ground(COG), speed over ground(SOG), and many others are all defined as "clockwise". The bible for marine navigation is called "Bowditch - The American Practical Navigator" and you will always find a copy on any large vessel. There is an online copy at: http://www.irbs.com/bowditch/ Open chapter 1 and read page 5 and 6 for the definition of direction, heading and bearing. For Bearing it has: Bearing (B, Brg.) is the direction of one terrestrial point from another, expressed as angular distance from 000° (North) clockwise through 360°. All the navigation data that is generated and archived by the ship's nav systems that I work on uses "clockwise" for angles. I assume the above definitions applies to all forms of navigation. Anybody who has ever flown an airplane knows that their compass heading is always measured "CLOCKWISE" starting from the Magnetic NORTH. For another source see: http://en.wikipedia.org/wiki/Bearing_%28navigation%29 It is essential that this enhancement support clockwise drawing of angles otherwise it is not going to do me(or other potential users) much good. I like your option 3. This should provide the most flexibility. I've thought about making this subroutine a little more general. I initially tried something like: int msProjectAngle(projectionObj *in, projectionObj *out, pointObj *point, double *angle) But I quickly discovered in mapdraw.c I did not have easy access to the original unprojected point. So I was forced to use the projected point which eliminated the need for the "in" projection. I also needed access to the latlong projection for the algorithm to work which forced me to pass the map object. So the subroutine has deviated from the "standard" used in mapproject.c. Not sure if this matters or not. Right now this subroutine uses the north pole as the reference point so I would probably rename it to something like "msProjectAngleTrueNorth". To make it more general one could include a reference point in the input parameter list. For the truenorth case one would just pass the reference point of 90N,0E. This would also mean adding a reference point directive to the mapfile. This might start to get complicated fast? What is involved in an RFC? -Steve
comment:6 by , 17 years ago
I decided to play around with ESRI's ArcMap and see how they do this. When you rotate a symbol you are given a choice of two rotation styles: 1) Geographic 0| | | 90 ----------- 270 | | |180 2) Arithmetic 90| | | 0 ----------- 180 | | |270 The default is Geographic. The "Geographic" style is clockwise relative to "north" which is what I need. But I played around with different projections and as far as I can tell the ESRI software does not have the smarts to draw the geographic angles correctly on these projections. But the software I have is somewhat old so maybe this works in later versions. -Steve
comment:7 by , 13 years ago
Did anything ever happen in Mapserver to implement such a thing as described in this enhancement report?
comment:9 by , 13 years ago
As far as I can tell nothing has been done on this. What will it take to get this moving again?
comment:10 by , 13 years ago
Description: | modified (diff) |
---|
Just like for any enhancement, it would need a dev to champion it, prepare a RFC and discuss it on the -dev list, and eventually commit, update docs and support any bug/side-effect that may arise once it is released.
In a previous comment you asked "What is involved in a RFC?"... the best way to find out is to look at a few recent RFCs (there are several good examples in the RFC 60-69 range) and the corresponding discussions in the mapserver-dev archives. If you want, you can prepare the RFC yourself and propose it on the -dev list for discussion/approval. Then if it is approved you could eventually contribute a patch for code and docs via this ticket... then the last missing bit will be to find a committer to review and commit your patches. Another option is to convince (or hire) one of the devs to do this for you of course.
comment:11 by , 13 years ago
Cc: | added |
---|
Proposed patch for mapdraw.c