%let name=drag; filename odsout '.'; %let state=NC; /* http://www.autoport.us/Drag%20Strips/NC%20Drag%20Strips.htm http://www.dunnbensondragstrip.com/ http://www.staginglight.com/links/trackfinder.html#NC */ data my_zips; length track_url $ 200; label track_url='URL'; label track_name='Name'; infile datalines pad truncover; input zip track_name $ 7-99 track_url $ 101-200; datalines; 28383 710 Dragstrip (1/8 mile) http://www.710dragstrip.20m.com/ 27803 Brewer's Speedway (1/8 mile) http://www.na-motorsports.com/Tracks/NC/Brewers.html 28716 Canton Motorsports Park (IHRA) http://www.na-motorsports.com/Tracks/NC/Canton.html 28540 Coastal Plains Raceway Park (1/4 mile, NHRA, Div 2) http://www.coastalplainsraceway.com/ 27504 Dunn-Benson Dragstrip (1/8 mile, IHRA, Div 1) http://www.dunnbensondragstrip.com/ 27028 Farmington Motorsports Park (1/8 mile, IHRA, SWC 1, Pro-Am 9) http://www.farmingtonmotorsportspark.com/ 28304 Fayetteville Motorsports Park (1/4 mile, IHRA, Div 9) http://www.fayettevillemotorsportspark.com/ 28444 Harrells Raceway (1/8 mile) http://www.harrellsraceway.com/ 28501 Kinston Drag Strip Motor Sports (1/8 mile race, 1/4 mile test/tune IHRA, SWC 1, Pro-Am 9) http://www.kdsmotorsports.com/ 28364 Maxton Drag Strip http://www.ecta-lsr.com/?page_id=2 28115 Mooresville Dragway (1/8 mile, IHRA, SWC 1, Pro-am 9) http://www.mooresvilledragway.com/ 28560 New Bern Motor Sports http://www.newbernmotorsports.com/contact/ 27944 Northeast Dragway (1/8 mile, IHRA, Div 1) http://www.northeastdragway.com/ 27928 Outerbanks Speedway (1/8 mile, IHRA, Div 1) http://www.outerbanksspeedway.com/ 27283 Piedmont Dragway (1/8 mile, IHRA, SWC 1, Pro-am 9) http://www.piedmontdragway.com/ 28379 Rockingham Dragway (1/4 mile, IHRA, SWC 1, Pro-Am 9) http://www.rockinghamdragway.com/ 27573 Roxboro Motorsports (1/8 mile, IHRA, Div 1) http://www.roxboromotorsports.com/ 28152 Shadyside Dragway (1/8 mile) http://www.shadysidedragway.com/directions.html 28377 Thunder Valley Dragway http://www.na-motorsports.com/Tracks/NC/ThunderValleyRP.html 27863 Wayne County Dragstrip (1/8 mile) http://www.na-motorsports.com/Tracks/NC/WayneCountyDrag.html 28697 Wilkesboro Raceway Park (1/8mile, IHRA, Div 1) http://www.wilkesbororacewaypark.com/ 29598 North Myrtle Beach Drag Strip http://www.raceindustry.com/Racetrack_Locator/1659/North_Myrtle_Beach_Drag_Strip/index.html ; run; /* Look up the longitude/latitude for the zipcodes */ proc sql; create table circle_anno as select my_zips.*, zipcode.city, -1*zipcode.x as longitude, zipcode.y as latitude /* If you don't have the new v9 zipcity() function, could merge in city name here */ /* , zipcode.city */ from my_zips left join sashelp.zipcode on my_zips.zip=zipcode.zip; quit; run; /* Convert degrees to radians, and use new v9 zipcity() function to get city name */ data circle_anno; set circle_anno; length city $ 30; city=scan(zipcity(zip),1,','); x=atan(1)/45 * longitude; y=atan(1)/45 * latitude; run; /* Create annotate 'circle' and chart-tip info for the city Also, for fun, add a url link to get weather info */ data circle_anno; length function style color $ 8 position $ 1 text $ 20 html $1024; retain xsys ysys '2' hsys '3' when 'a'; set circle_anno; /* Create html title= charttip and href= drilldown for each annotated marker */ html= 'href='|| quote( trim(left(track_url)) ) ||' '|| 'title='|| quote( trim(left(substr(track_name,1,index(track_name,'(')-1))) || '0d'x || trim(left(substr(track_name,index(track_name,'(')))) ) ; %let lightred=cx800000; %let darkred=cx550000; /* Annotate a solid-filled pie at each zipcode */ /* a pie centers better than the 'special' dot character */ function='pie'; color='black'; style='psolid'; position='5'; rotate=360; size=2.7; anno_flag=1; output; /* Gray border around the outside */ color='graydd'; style='pempty'; output; /* donut hole inside the pie */ color='white'; style='psolid'; size=size/2.3; output; /* center dot/spindle */ color='black'; style='psolid'; size=.15; output; run; /* Use unprojected maps.county, rather than maps.uscounty, so you can annotate graphics at long/lat, and re-project it. */ data my_map; set maps.county (where=(fipstate(state)="&state")); run; /* Creates an annotate version of the county outlines, so that you can annotate them such that the county outlines appear "on top of" the area circles - this isn't essential, but it looks a lot better. This gives the circles a more 'transparent' look, and allows you to see the county outlines that would have otherwise been covered up by the circles. (This code is slightly modified version of some code provided by tech support.) */ /* project the map, and the annotation (this 'straightens' the selected state map) */ data combined; set my_map circle_anno; run; proc gproject data=combined out=combined dupok; id state; run; data my_map circle_anno name_anno; set combined; if anno_flag=1 then output circle_anno; else if anno_flag=3 then output name_anno; else output my_map; run; /* Layer the annotate so that they are drawn in desired order, and so that the proper pieces look "on top" */ data top_anno; set circle_anno name_anno; run; /* Create an annotated 'shadow' to go behind the map. It's ok to use the already-projected map for this. */ data anno_shadow; set my_map; orig_order+1; run; proc sort data=anno_shadow out=anno_shadow; by county segment orig_order; run; proc gremove data=anno_shadow out=anno_shadow; by county; id county; run; data anno_shadow; length COLOR FUNCTION $ 8; retain FX FY FUNCTION; set anno_shadow; by county segment; xsys='2'; ysys='2'; color="&darkred"; size=1.75; when='B'; style='msolid'; if first.segment then do; FUNCTION = 'poly'; FX = X; FY = Y; end; else if FUNCTION ^= ' ' then do; if X = . then do; X = FX; Y = FY; output; FUNCTION = ' '; end; else FUNCTION = 'polycont'; end; if FUNCTION ^= ' ' then do; output; if last.segment then do; X = FX; Y = FY; output; end; end; run; /* Give a little x & y offset, so it will look like a shadow */ data anno_shadow; set anno_shadow; x=x+.0004; y=y-.0006; run; /* Annotate a logo picture onto the map ... */ /* This image & drilldown could be used for a 'sponsor' of the page */ data img; length function text $ 8; length color $ 8 imgpath $ 100; xsys='3'; ysys='3'; hsys='3'; when='A'; html='title="Skate" href="http://www.traillink.com/TL_Active_Pages/TrailSearch/default.asp" '; function='move'; x=0; y=0; output; function='image'; x=x+30; y=y+35; imgpath='test_rollerblade_lightning_07.gif'; style='fit'; output; /* Image downloaded from http://www.sports-events.org/aventure.com/test_rollerblade_lightning_07.gif */ /* function='image'; x=x+25; y=y+35; imgpath='RTX700.jpg'; style='fit'; output; */ /* Image downloaded from http://www.seskate.com/skates/ilskate/images/RTX700.jpg */ function='move'; x=70; y=0; output; function='image'; x=x+30; y=y+20; imgpath='locomotive.jpg'; style='fit'; output; /* Image downloaded from http://www.765.org/Web_Images/fwle14.jpg */ run; /* The gradient and the shadow go behind (when='b') the rest of the map. I find it easiest to keep them in a separate annotate data set. */ data anno_back; set anno_shadow /* img */; if function ne '' then output; run; /* Modify the color in the d3d border */ ods path work.template(update) sashelp.tmplmst; proc template; define style styles.red3d; parent = styles.d3d; replace Output from Container / borderstyle = outset background = colors('tablebg') bordercolorlight = &lightred bordercolordark = &darkred borderwidth = 9 rules = all frame = Box cellpadding = 5 cellspacing = 1 bordercolor = colors('tableborder'); end; run; GOPTIONS DEVICE=gif; goptions xpixels=935 ypixels=485; /* goptions cback=cxffffff transparency; */ ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" (title="Drag Strips in NC") style=red3d gtitle gfootnote ; goptions border; goptions gunit=pct htitle=10 htext=4.5 ftitle="arial/bo" ftext="arial" ctitle=&lightred ctext=&lightred; goptions iback='checker.gif'; title link="http://www.staginglight.com/links/trackfinder.html#NC" box=1 bcolor=white ls=3.0 "Drag Strips in NC"; title2 a=90 h=5pct " "; title3 a=-90 h=5pct " "; /* Color for the map areas */ pattern1 color=graydd value=solid; proc sql; create table my_mapdata as select unique state, fipstate(state) as st, county from my_map; /* Merge in the county name */ create table my_mapdata as select my_mapdata.*, cntyname.countynm from my_mapdata left join maps.cntyname on my_mapdata.state=cntyname.state and my_mapdata.county=cntyname.county; /* Merge in the name of the cities in that county */ create table my_mapdata as select my_mapdata.*, uscity.city, uscity.pop from my_mapdata left join maps.uscity on my_mapdata.state=uscity.state and my_mapdata.county=uscity.county; /* Now, narrow it down to just the largest city in each county */ create table my_mapdata as select * from my_mapdata order by county, pop descending ; quit; run; data my_mapdata; set my_mapdata; html= 'title='||quote( trim(left(countynm))||', county' ) ||' ' /* || 'href='||quote( 'http://maps.google.com/maps?t=k&hl=en&q='||trim(left(city))||', '||trim(left(st)) ); 'href='||quote('http://maps.google.com/maps?q=Palm+Bay,+FL&ll=28.533297,-80.838089&spn=0.051413,0.058107&t=k&hl=en'); */ ; /* Draw the map */ proc gmap map=my_map data=my_mapdata anno=top_anno; id state county; choro state / coutline=&lightred anno=anno_back nolegend discrete des="" html=html name="&name"; run; quit; ODS HTML CLOSE; ODS LISTING;