Sexy Map Application
Overview
I'm [http://www.personaltelco.net/static/node/ playing with map making] to visually explain PersonalTelco's coverage around PortlandOregon. I'm mostly interested in making the map look sexy. I'm using the [http://www.trans.ci.portland.or.us/bicycles/bikemap.pdf City of Portland Office of Transportation Bike Map] as a starting point. I grabbed a few tools on my AppleMacintosh that are simple to play with by hand and then started automating parts. I'm using AppleScript because it's been a while and I am curious where it's at these days. --DarrinEden
To Do
- The downtown cluster is too blobby making it hard to pick any one spot. It also implies way more coverage than there really is.
- Partial: reduce spot radius
- Automate the imagemap portion of the process.
- Partial: 2d compensation
Code
tell application "Finder" to set homePath to (home as string)
set pdxSpotList to (homePath & "Desktop:spots.xls") set pdxMapOriginal to (homePath & "Desktop:bikemap.pdf" as alias) set resultGraphic to (homePath & "Desktop:pdx.png") set dotRadius to 12 set resultWidth to 450 set cropX to 19 set cropY to 248
set myList to {}
tell application "Microsoft Excel"
- Open pdxSpotList set myRow to 1 repeat
- set tuple to {} repeat with myColumn from 1 to 3
set currentCell to "R" & myRow & "C" & myColumn as string set cellText to text of Cell currentCell if cellText is "" then exit repeat set end of tuple to cellText
- set tuple to {} repeat with myColumn from 1 to 3
end tell
tell application "Adobe Photoshop CS"
- activate open pdxMapOriginal set maxX to 0 set maxY to 0 set minX to 1500 set minY to 1500 repeat with z in myList
- set spotName to item 1 of z set x to item 2 of z set y to item 3 of z if x is greater than maxX then set maxX to (x + dotRadius) if y is greater than maxY then set maxY to (y + dotRadius) if minX is greater than x then set minX to (x - dotRadius) if minY is greater than y then set minY to (y - dotRadius) make new art layer at beginning of current document ¬
- with properties {name:spotName, blend mode:normal}
var selectionChannel = new ActionReference();
- selectionChannel.putProperty( charIDToTypeID( \"Chnl\" ), charIDToTypeID( \"fsel\" ) );
var makeSelection = new ActionDescriptor();
- makeSelection.putReference( charIDToTypeID( \"null\" ), selectionChannel );
var selectionParameters = new ActionDescriptor();
- selectionParameters.putUnitDouble( charIDToTypeID( \"Top \" ), charIDToTypeID( \"#Pxl\" ), selTop ); selectionParameters.putUnitDouble( charIDToTypeID( \"Left\" ), charIDToTypeID( \"#Pxl\" ), selLeft ); selectionParameters.putUnitDouble( charIDToTypeID( \"Btom\" ), charIDToTypeID( \"#Pxl\" ), selBottom ); selectionParameters.putUnitDouble( charIDToTypeID( \"Rght\" ), charIDToTypeID( \"#Pxl\" ), selRight ); makeSelection.putObject( charIDToTypeID( \"T \" ), charIDToTypeID( selShape ), selectionParameters ); makeSelection.putUnitDouble( charIDToTypeID( \"Fthr\" ), charIDToTypeID( \"#Pxl\" ), featherAmt ); makeSelection.putBoolean( charIDToTypeID( \"AntA\" ), antiAlias );
executeAction( charIDToTypeID( \"setd\" ), makeSelection, DialogModes.NO );
- with arguments {selShape, selTop, selLeft, selBottom, selRight, antiAlias, featherAmt}
- fill selection of current document with contents ¬
- {class:RGB color, red:81, green:172, blue:205} blend mode ¬ vivid light opacity 90 without preserving transparency
-- display dialog "minX: " & minX & " miny: " & minY & " maxX: " & maxX & " maxY: " & maxY crop current document bounds {cropX, cropY, 918, 1254} -- {minX, minY, maxX, maxY} -- resize image current document width resultWidth -- save current document in resultGraphic as PNG with copying
- set spotName to item 1 of z set x to item 2 of z set y to item 3 of z if x is greater than maxX then set maxX to (x + dotRadius) if y is greater than maxY then set maxY to (y + dotRadius) if minX is greater than x then set minX to (x - dotRadius) if minY is greater than y then set minY to (y - dotRadius) make new art layer at beginning of current document ¬
end tell
tell application "TextEdit"
- set imageMapText to "" set scaleX to 889 set scaleY to 1006 repeat with z in myList
- set spotName to item 1 of z set x to item 2 of z set y to item 3 of z set x to round ((x - cropX) * (resultWidth / scaleX)) set y to round ((y - cropY) * ((resultWidth / scaleX) * scaleY) / scaleY) set x to x - 3 set y to y - 4
set AppleScript's text item delimiters to " " set stringParts to text items of spotName set AppleScript's text item delimiters to "" set spotName to stringParts as text
set imageMapText to imageMapText & "<area shape=\"circle\" alt=\"" & spotName & "\" coords=\"" & x & "," & y & "," & (round ((dotRadius + 3) / 2)) & "\" href=\"#" & spotName & "\">" & return
- set spotName to item 1 of z set x to item 2 of z set y to item 3 of z set x to round ((x - cropX) * (resultWidth / scaleX)) set y to round ((y - cropY) * ((resultWidth / scaleX) * scaleY) / scaleY) set x to x - 3 set y to y - 4
end tell
Data
Pioneer Courthouse Square Area |
514 |
737 |
Powells Bookstore |
499 |
715 |
Stumptown Café |
536 |
722 |
Anna Bannanas |
439 |
653 |
World Cup Coffee and Tea |
465 |
693 |
Ecotrust |
502 |
678 |
Coffee Plant |
513 |
733 |
Backspace |
525 |
713 |
South Park Blocks |
486 |
781 |
Moonlight Staffing at PGE Park |
452 |
736 |
Couch Park |
454 |
663 |
The Basement Public House |
635 |
776 |
Red Wing Coffee and Baking |
604 |
804 |
Rose and Raindrop |
637 |
745 |
Subway Sandwich Restaurant |
756 |
800 |
Hawthorne Hosteling International |
735 |
800 |
Costellos Travel Caffe |
690 |
639 |
Hollywood Library |
792 |
628 |
Arbor Lodge Park |
441 |
402 |
Irving Park |
689 |
550 |
Red and Black Café |
678 |
850 |
Ugly Mug Coffeehouse |
622 |
1125 |
The Crow Bar |
534 |
526 |
Cafe La Dolce Vita |
645 |
472 |
Urban Grind Coffeehouse |
701 |
684 |
Cedar Hills Crossing Shopping Center |
40 |
1234 |
Portland Independent Media Center |
752 |
769 |
Northstar Coffeehouse |
508 |
356 |
Goldrush Coffee Bar |
602 |
592 |
WSMF |
722 |
760 |

