############################################################# # # SML Script layer to draw a north arrow. # # NOTE! This script assumes that the SML layer is in some # coordinate system other than Lat/Lon (Which is unfortunately # what the SML layer seems to default to). You MUST change # the coordinate system of the layer to State Plane or UTM # or something that uses feet or meters for coordinates. # If you try to draw this using degrees, you'll get a very # tall and thin arrow. # ############################################################### # Fill in parameters here... # Angles are in degrees from vertical. Positive is to # the left, negative is to the right numeric mn_angle = -7.2; # Degrees to magnetic north numeric gn_angle; ############################################################### # Get the angle to true north from a map group. # This code may have to be tweaked for another layout. # It assumes that the group you want is the one just # before the group with this script (in drawing order). class Group group; group = ThisLayer.group.PrevGroup; gn_angle = -group.AngleToNorth; ############################################################## # Generate the strings. Would like to have this produce # Degrees, Minutes, Seconds, but decimal degrees is ok for now string mn_anglestr$ = sprintf("%.1f", abs(mn_angle)); string gn_anglestr$ = sprintf("%.1f", abs(gn_angle)); numeric mn_theta = mn_angle + 90; # Drawing wants angle from x-axis numeric gn_theta = gn_angle + 90; array numeric xs[6]; array numeric ys[6]; proc DrawStar(numeric cx, numeric cy, numeric size) { local numeric i, th; for i = 0 to 5 { th = 144 * i + 90; xs[i+1] = size * cosd(th) + cx; ys[i+1] = size * sind(th) + cy; } FillPolyLine(xs, ys, 5); # Even/Odd winding rule leaves a hole in the middle # of our star. Fill it with a circle whose radius # is computed to intersect with the corners of the # pentagon shaped hole. Could do this a different # color if we wanted. Maybe do it before the actual # polygon fill to get a different colored hole. FillCircle(cx, cy, size * cosd(36) / 2); } #============================================ # Draw a vertical line with a star above it. numeric r; SetColorName("black"); r = 200; MoveTo(0,0); DrawTo(0,r); DrawStar(0, r+20, 20); #============================================ # Draw arrow pointing to Magnetic north numeric x, y; r = r * .9; x = r * cosd(mn_theta); y = r * sind(mn_theta); MoveTo(0, 0); DrawTo(x, y); # Draw a triangle at the top of it FillArcWedge(x, y, 20, 20, 270 + mn_angle, 30); SetColorName("gray"); DrawArc(0, 0, r, r, 90, mn_angle); SetColorName("black"); DrawTextSetFont("Times.ttf"); DrawTextSetHeight(30); MoveTo(x + 10, r/2); DrawTextSimple(mn_anglestr$); MoveTo(x, y + 5); DrawTextSimple("MN"); #======================================================== # Draw Grid North if (gn_angle) { r = r * .9; x = r * cosd(gn_theta); y = r * sind(gn_theta); MoveTo(0,0); SetColorName("black"); DrawTo(x, y); SetColorName("gray"); DrawArc(0, 0, r, r, 90, gn_angle); SetColorName("black"); MoveTo(-50, y - 15); DrawTextSimple("GN"); MoveTo(-55, r/2); DrawTextSimple(gn_anglestr$); } #========================================================= # Dump some text about what Grid north is. numeric yh; DrawTextSetHeight(20); x = 100; y = r * .8; yh = 20; MoveTo(x, y); DrawTextSimple(group.Projection.System); y = y - yh; # Don't bother printing out the name if the system contains # the name. Example: "Universal Transverse Mercator" # contains the name "Transverse Mercator" if (!(group.Projection.System contains group.Projection.Name)) { MoveTo(x,y); DrawTextSimple(group.Projection.Name); y = y - yh; } if (group.Projection.Zone != "") { MoveTo(x, y); DrawTextSimple(sprintf("Zone: %s", group.Projection.Zone)); y = y - yh; } MoveTo(x, y); DrawTextSimple(group.Projection.Datum); y = y - yh; MoveTo(x, y); DrawTextSimple(sprintf("Ellipsoid: %s", group.Projection.Ellipsoid));