Anne’s been gone all week, in Denver helping Emmi with Iris while Kyle came here to do some real estate transactions. He went home Friday, and I’ve been living the bachelor life this weekend. I’m right now waiting for Anne’s much-delayed flight to arrive; I’ve got a little time to kill so here’s another post…
These are some pictures I took on a walk a few weeks ago. I was just rambling around, on Sand Island and across the Lehigh bridges, no special agenda but I did get a few nice photos, mostly of the river and of Monocacy Creek.
Nothing much to say here, I just thought I’d drop a few photos from the last day or so to show the fall colors. Last night our neighbors had a “roasted root” party, cooking potatoes, parsnips etc in their backyard fire pit, and today is the Halloween Parade; we’ll be doing a bike ride in costume beforehand. Fall is definitely here…
In The BackyardNorfolk SouthernAutumn Still WatersLehigh Canal And LeavesLehigh River Near NorthamptonThe D&L Near NorthamptonLehigh River SceneOn The D&L Near Northampton
I went out for a ride on Tuesday, heading west/north along the towpath but only going as far as the Taylor House brewpub in Catasauqua — I wanted to check out the new section of improved trail.
This was one of the few sections of trail left that had been open but unimproved (there is/was another one immediately north of this section, between Catty and Northampton, that also got fixed up recently), passable but still fun on a mountain bike. Much of the Lehigh Towpath was like this when I first started riding it, lo those many years ago. The trail is a pleasure to ride now, sure, but I miss those old days and the rougher, more “singletrack-ey” towpath. I only started riding this section north of Allentown maybe two years ago, and really enjoyed the feeling of being on “real trails” again, but hey that’s progress, and the new sections are actually pretty sweet. I believe the official ribbon cutting is today.
Meanwhile, same as it ever was: my bottom bracket developed a creak again (this is the Santa Cruz), and so I took a look and found that both the crank bolt and the right bearing housing had loosened. I cleaned and greased and tightened them down pretty hard yesterday and did another towpath ride (towards Easton this time), and I think I got it solved. For now.
Morning weigh-in: 171.5#, 11.5% BF (not great, not terrible)
Today was the first weigh-in since we got back from vacation, and it’s also the first “fast day” since before Denver — who diets on vacation? But now I’m back, and back in the groove.
I got in a towpath ride yesterday, my first bike ride in weeks. It was a beautiful warm sunny day, and Spring (which had just been starting to happen when we left), was in full bloom along the towpath. All sorts of flowers (phlox, king’s rocket) along the path, with fully greened-up trees all around, blooming with flowers of their own and filling the air with perfume, just perfect as I rode along the sun-dappled trail with the water sparkling next to me.
Anne went out earlier on a road ride with Julie, and reported that she could feel a positive effect from our weeks at altitude. I noticed it too: my perceived effort and my heart rate were both lower than I expected, and I seemed to be cruising along at a good clip too. Then I reached my turnaround, and realized I’d had a tailwind on the way out… Still, I felt pretty good considering my time away from the bike, and had a good overall pace despite the wind.
Today was the CAT/Bethlehem Bike To Work Day festivities and short ride, and in a few minutes I’m bicycling over to a doctor’s appointment. Bike bike bike…
So this weekend was our annual bike camping trip up the D&L to Jim Thorpe. A total of seven of us rode up, and our friend Predo, who was on “injured reserve,” drove to the campsite with our extra gear. It took us about six hours, with plenty of photo ops and snack breaks, and a few snafu’s…
We (Bill M, Jared, Sara, Anna Z, Ed, and Anne and I) started at CAT, and took the roads until we got to Northampton, where we crossed the Lehigh and picked up the trail. Lunch was the “Diggity Dogs” food truck at the Slatington Trailhead, and then it was another fifteen miles to downtown Jim Thorpe. A trip to the supermarket, then the long climb from the river to our campsite, and we were done for the day. Predo met us at the campground, and Rick & Shari arrived not long after.
Concrete Phone Booth
Ed and Bill
Bill, Ed and Me
Saturday we rode into town — which was a madhouse, the Fall Festival was in full swing — met Shari and Rick (they are NOT into camping) and continued north along the trail, picking up Matt & Diet at the Glen Onoko trailhead. We were now eleven strong…
The trail was fairly quiet at the start, but it was a beautiful fall day if a bit drizzly, and things became pretty crowded after a while. We got to Rockport, which was another madhouse, with bicycle outfitters dropping off cyclists by the busload, and that’s where we ate lunch and did some very entertaining people-watching… Our goal and turn-around was Buttermilk Falls, just a half mile past lunch and always a good photo-op.
A View of the Rockport Tunnel
Buttermilk Falls
Group Shot
Anne and Me
Looking Upstream
Me at “The Photo Rock”
Jared at “The Photo Rock”
The Crew
Sara at “The Photo Rock”
On the way back we met up with Ben and Candace, which brought our group up to our full strength — 13 riders! One more photo session at the usual spot, and our excursion began winding down; we said goodbye to Matt & Diet at Glen Onoko, and rode back up to camp. Dinner was basically a pizza party, and we had one final addition: Gary L who was joining us for the Sunday return ride.
At The Campfire
At The Campfire
Mauch Chunk Lake
Our Campsite
Sunday was the return. Ben and Candace took off for Philly, and Rick and Shari had gone home the night before, so we were now down to eight. The ride was pretty uneventful, but we did switch things up by taking the Nor-Bath Trail from Northampton over to Bicentennial Park, before finishing on the road.
…AND I finally got a photo of that spooky “house on the hill” at Lehigh Gap.
I have a bell on each of my offroad bikes, but I normally don’t use them — I prefer verbal communication when I overtake someone, since it’s more effective and (in my opinion) way more polite. Yesterday, on the way back from the Museum, I came across a little old lady walking her German shepherd, and called out my usual “hi, passing on your left!” She moved over to the left (oops!), but by that time I’d stopped, and we were doing that neighborly, chuckling “yes, hello, passing you on the towpath” sort of greetings and negotiation, when her dog just absolutely went bonkers — barking, snarling, leaping at me at the end of its leash. It looked for all the world like an attack dog in some kind of video.
It dragged the woman over as it came at me, completely out of her control — luckily it was not as hardcore as it wanted me to believe, because when it attacked it went for my ankle. Luckily again, I was wearing street clothes, including hiking boots, and the dog couldn’t really get a purchase on them. (I’m guessing it happened too fast for me to react, since I felt strangely calm throughout the entire situation.) All the while the woman was yanking at the dog, and when she finally got it under control I got a little snarky and said “good thing your dog was on a leash.”
I don’t think she got it, because her reply was “well, it is the law.” I just rode off…
Her parting shot, once I was down the trail? “If you had a bell you could have warned me!” I was tempted, but I didn’t ring my bell.
I was supposed to go for a lunch-hour ride today with Greg H, but his office was shorthanded and he had to bail. I went out anyway, just for an easy towpath ride, but by about five miles I was sluggish and exhausted and couldn’t go on. I stopped at Farmersville Road, ate some shot blocks and two GU packs, sat for a while for them to take effect, and then moseyed my way home. I think I guessed right: whatever ailed me was nutritional, and I felt much better on the way back.
I also think I lucked out, because with Greg I’m sure we would have done either Lehigh or Sals, and I would have been dying. I still have no idea what could have made me so drained — I haven’t overdone the physical activity lately, and we’ve been eating much better, since our return, than we have in about a month.
I’ve been thinking a lot about the economic impact of the towpath lately, and have been looking to the Great Allegheny Passage as a model, where many food and lodging places have popped up to cater to the cycle touring crowd. I know that the D&L Corridor people are also looking at various businesses and how the towpaths might impact them, but I believe that they are looking at it from a county-wide perspective, when they should probably really be looking at impact within a few blocks of the path, and or at least within about a mile of the river — would you decide to take a fully loaded touring bike miles out of your way, and probably up some hill to get away from the river, just for say, lunch, if you didn’t absolutely have to? So, that got me thinking about the question: what restaurants, hotels, bike shops, and other amenities are actually within a mile of the relevant sections of the Delaware and Lehigh Rivers?
(This was a good first approximation, but it’s surely a naive way of looking at the problem, since there are many places within a mile of the river as the crow flies, that are not actually within a mile, or maybe even many miles, of anyplace accessible from the towpath — and places that will see towpath business will need to be located within a matter of blocks, not miles, from towpath access points. But I realized all that later as I thought more about the overall situation, and my first analysis of towpath business prospects was what I worked on first.)
The way I looked at it, my original problem broke down into two parts. First, what is the region within one mile (or whatever distance) from the river, and second, what are the amenities within that region? The first part was fairly straightforward, but the second, which looked like it would involve some kind of Google Maps search — and eventually it did — turned out to be more complicated than I thought…
Nifty QGIS: Five minutes of work to get the buffer zone.
I used QGIS to deal with the first part. I took as my reference some Pennsylvania aerial photos, plus a property map of Lehigh County, and created a new line vector (in a projection that uses feet as a unit of measure), following what looked like the middle of the Lehigh River from about Laurys Station to just past Bethlehem, and then I used the “Create Buffer” geoprocessing tool to create a vector polygon buffer region around that section of river, whose distance from my line vector was 5280 feet, in other words, one mile. That part worked great, but what to do with my buffer region?
My first thought was to take the buffer vector and export it to a KML file, import that KML file into a custom Google Map (using Google’s “My Maps” personal map creation/editing feature), and then “do something” with it. That all worked great as well, up until the “do something” part — the KML file, and the personal map, were not much use when it came to customizing a map search.
I did find online, however, that there were some things you could do with polygonal regions, and testing locations (such as the ones returned from search results) to see if they fell within those regions, using the Google Maps API. This added two new steps: first I had to re-export my buffer region, this time as a GeoJSON file because that was what the API would accept, and I also had to sign up for an API key from Google Maps. Both of these were also straightforward and easy to do.
The final step was to put it all together: make a web page, and (with some javascript), load and draw the GeoJSON file, run a search (for restaurants, in my experimental code), and then find and display results that fell within my region. Code code code, give it a try… nothing. I was able to load the file and see my region, but no place results would be displayed.
Turns out, there is more than one Polygon type in the API, and the one created by loading a GeoJSON file is different than the one you can test locations against; I would have to convert my polygon from one form to another. (This seemed to me a bit much, especially since I thought I should have been able to load the original KML file and it would “just work.” After all, isn’t KML a Google thing, and kind of a standard?) No matter, the conversion process from one polygon to the other looked as straightforward as every other step so far, so I just added it to the end of the task chain. Code code code, give it a try… nothing, and here is where it started to get really frustrating.
I couldn’t for the life of me figure out what was going wrong, it looked like I did things exactly the way I was supposed to but my new, converted polygon could not be made, and it looked like the original polygon actually was empty, even though it was drawn on screen. I eventually used a callback routine from the GeoJSON loading function to get the polygon coordinates, and for some reason that worked.
That gave me my clue: the “some reason” was that the callback was not executed until after the file was done loading, so the conversion routine had something — a non-empty original polygon — to work with, while in my original code the rest of the script wouldn’t wait for the file to finish loading before continuing, so there really was nothing to work with yet when I tried to do the conversion. That took three paragraphs to write, but more than a day to work out…
I didn’t really like my solution: if you’re forced to use callbacks like that, you end up going down the rabbit hole, callback after callback after callback, just to get some semblance of sequential execution. (Meantime, I found that some methods did not suffer from these kinds of problems, they seemed to wait for the data to load before trying to work on it. Strangely enough, all the simple API examples I found at Google used these methods instead of the one I needed.) Eventually I set up a wrapper function to hide the messy details and just get me my goddamned polygon from the goddamned GeoJSON file.
Anyway, here is my demo map:
UPDATE (7/26/2018): This map will stop working after July 30th, because the “radar search” function (see script below) has been deprecated by Google Maps. I may take some time to update the script — which I’ll mark with another update — but then again I may not, because this is a low-usefulness, low-visibility, low-priority thing for me, and also because fuck Google.
And here’s my script. Most of this is based on Google Maps API examples, but the function getBuffer() loads the data, and createBufferPolygon() is the wrapper that creates the polygon object:
var myNewMap; // the google map
var myPlaceService; // object for google places api
var myBufferPoly; // the polygon that holds the buffer region
var myInfoWindow; // info window for the selected place
// the callback function from loading the API, where everything actually happens
function initMap() {
myNewMap = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.672628, lng: -75.422778 },
mapTypeId: google.maps.MapTypeId.TERRAIN,
zoom: 11
});
var bikeLayer = new google.maps.BicyclingLayer();
bikeLayer.setMap(myNewMap);
myBufferPoly = createBufferPolygon(
'lbuf2.geojson',
'lehigh',
myNewMap,
true,
'green'
);
myPlaceService = new google.maps.places.PlacesService(myNewMap);
myInfoWindow = new google.maps.InfoWindow();
getSearch();
}
// this is the wrapper function, which calls the function that loads the GeoJSON file
// after creating the polygon to hold the buffer region
function createBufferPolygon(url, featureName, map, isVisible, polyFillColor) {
var bufPoly = new google.maps.Polygon({
map: map,
clickable: false,
visible: isVisible,
fillColor: polyFillColor
});
getBuffer(url, featureName, bufPoly);
return bufPoly;
}
// this function loads a GeoJSON file containing a named polygon
// then adds it to the given polygon object
function getBuffer(url, featureName, poly) {
var bufGeom;
var bufferData = new google.maps.Data();
bufferData.loadGeoJson(
url,
{idPropertyName: 'name'},
function(featarr) {
bufGeom = bufferData.getFeatureById(featureName).getGeometry();
poly.setPaths(bufGeom.getAt(0).getArray());
});
}
// finds all restaurants within 15km of a certain location
function getSearch() {
var request = {
location: {lat: 40.703117, lng: -75.416561 },
radius: 15000,
keyword: 'restaurant'
};
myPlaceService.radarSearch(request, displayResults);
}
// displays search results that fall within the buffer region
function displayResults(searchResults, searchStatus) {
if (searchStatus !== google.maps.places.PlacesServiceStatus.OK) {
console.error("getSearch error: " + searchStatus);
return;
}
for (var i=0, result; result=searchResults[i]; ++i) {
if (google.maps.geometry.poly.containsLocation(
result.geometry.location, myBufferPoly)) {
addMarker(result);
}
}
}
// adds marker for selected places
function addMarker(place) {
var marker = new google.maps.Marker({
map: myNewMap,
position: place.geometry.location,
icon: {
url: 'http://maps.gstatic.com/mapfiles/circle.png',
anchor: new google.maps.Point(10, 10),
scaledSize: new google.maps.Size(10, 17)
}
});
google.maps.event.addListener(marker, 'click', function() {
myPlaceService.getDetails(place, function(result, status) {
if (status !== google.maps.places.PlacesServiceStatus.OK) {
console.error(status);
return;
}
myInfoWindow.setContent(result.name);
myInfoWindow.open(map, marker);
});
});
}
That’s a lot of work for something that solves the wrong problem! My next look at this will likely just involve finding the access points, and doing Google searches near each one — soooo much less elegant…