Showing posts with label panorama. Show all posts
Showing posts with label panorama. Show all posts

Friday, 2 August 2013

Calculating Line of Sight with PostGIS 2.1



For the past few years I’ve been working a lot with 360 degree panoramic photos and more recently I’ve been putting more and more effort in to get to harder to reach places to get these photos. It was only just over 1 month ago now that I decided to do a 3 day walk which was dedicated to take a single panorama!

Lots of my recent panoramas have been in mountainous regions and, I’m not sure about you, but when I’m in areas with lots of mountains I normally find myself wondering, which mountain that is over there to the North-East. It wasn’t until I discovered the existence of a mobile phone application which helps with this that I decided to try and implement something into my panoramas.

My panoramas can all be viewed on my website at www.davidrowley.co.uk/pano.php here the panoramas are viewed interactively, so you can scroll around the panorama, look up, look down, round, zoom in and out. I had already been using PostGIS 2.0 for calculating distances to other panoramas, this allowed me to find the nearest panoramas from another panorama accurately.

Once I had seen the mobile application which named the peaks I decided that I would try to do something similar in my panoramas. The platform I was using at the time was perfect to allow me to do this. I use some software called krpano, this allows my flat 360x180 degree panoramas to become interactive. It also allows many other things to be done, you can have hotspots to other panoramas and even include video in your panorama to bring things to life!

KRPano is programmed by making reference to XML files which contain setup information and code to tell the panoramic viewer what to do. For me I write these XML files dynamically using PHP and I use PHP to read details about the panorama directly from my PostgreSQL 9.2 database. I was really already half way to displaying the names of the mountain peaks in my viewer. It was just a simple matter of gathering up some peak data and writing some code to layer them onto the pano. Remember I didn’t want to have to name my peaks manually… I wanted to have this done automatically.

The first step was gathering some peak information from open street maps. I now had a fairly large list of mountains loaded into a table in my database. I then added a Geography column to the table and set a trigger to update this column from the latitude, longitude and elevation columns. With about 1 day of work my panoramic viewer was showing me mountains. I had written algorithms to calculate the pitch/angle to the top of the mountain based on the elevation of the mountain and the elevation of the panorama along with the distance between the 2. The algorithm takes into account the curvature of the earth, but still will need some more work to correct for atmospheric refraction.



With the open street map layer enabled a typical scene from my panoramic viewer now looked like this



To get this far I created a single function that sits in the database and when passed a location and radius it returns a list of mountain peaks which are within that radius, along with the bearing and pitch to that peak.

When I clicked refresh on my web browser I was really happy to see the scene above. I had learned a lot about PostGIS on this day and was fairly happy with what the outcome was. It was just a matter of hovering over the blue triangle and it would tell you the name and elevation of the peak behind it!

Now, if you look more closely at the peaks in the above image then you’ll see that some of the triangles are grouped quite closely together. Let me zoom in and give you a closer look:



Annoyingly here the mountain named “Tableland” is slightly lower and further away than the slightly higher “Gordon’s Pyramid”. So really listing Tableland was wrong here as it could not actually be seen!

This was not the only problem. I was also hitting problems were certain panorama the mountains did not line up despite me being totally accurate with their locations and elevations.




In the above image you can see that Mount Cook is much lower than it’s meant to be. The problem here lies with the panorama not being perfectly level… Something which is very hard to do in mountainous areas even after you make sure your tripod is as level as you can get it.

So it seems there’s going to be a fair bit more work to do to get this working as I want it.

Calculating Line of Sight


The first step was to gather up some elevation data. Thanks to NASA and some hard work from a dedicated man in Scotland most of the world’s elevation data is available for free here http://www.viewfinderpanoramas.org/Coverage%20map%20viewfinderpanoramas_org3.htm

I started by downloading all the elevation data for New Zealand, which when I loaded it into the 3dem software which can be found on the viewfinderpanorama.org website I got this familiar shape.


The next step was to figure out some way to load these files into my PostgreSQL database. Luckily this is very simple as PostGIS comes with a tool to turn these elevation files into an SQL file which can be imported with psql.

I put all my .hgt into 1 directory and ran the following command:

"C:\Program Files\PostgreSQL\9.2\bin\raster2pgsql.exe" -s 4326 -I -C -M "HGT\*.hgt" -F -t 75x75 public.demelevation > elevation.sql

The above command creates a file called elevation.sql which contains all the CREATE TABLE command and imports all the data then properly constraints the tables to help PostgreSQL’s query planner do its job efficiently.

Before working with this elevation data I had no idea what a raster was. So if you’re in the same boat, then it is basically a raster when you’re talking about spatial data is a tile or array of data relating to a patch of the surface of the planet. A raster contains its anchor point and contains information about the resolution of the raster, and is generally very much like a bitmap. The remainder if the data is just an array of values. In the case of the raster’s that we are working with, this array of values is elevation data in metres.

Once I loaded the above file I could find the elevation for any point in New Zealand with the following command:
SELECT ST_VALUE(e.rast, ST_SetSRID(St_MakePoint(170.1420703, -43.594937), 4326))
FROM demelevation e
WHERE ST_Intersects(e.rast, ST_SetSRID(St_MakePoint(170.1420703, -43.594937), 4326));



What’s happening here is, we first need to find the raster tile for the location that we’re looking in, so ST_Intersects in the WHERE clause will gather all rasters with data about this location. With the resulting rasters, in this case, since we have no overlap then we only should have 1. We then ask that raster for its value for the same location. When I run this command I get the following:

test=# SELECT ST_VALUE(e.rast, ST_SetSRID(St_MakePoint(170.1420703, -43.594937), 4326))
test-# FROM demelevation e
test-# WHERE ST_Intersects(e.rast, ST_SetSRID(St_MakePoint(170.1420703, -43.594937), 4326));
 st_value
----------
     3712
(1 row)


Time: 1.499 ms

This is the approximate elevation of Mount Cook, the highest mountain in New Zealand. Also you might notice that the database returned this result to me quite quickly at around 1.5 milliseconds. This is amazingly fast and it's made possible by putting a gist index on the rast column.

So now it’s time to build a function which will calculate if there is a line of sight between 2 points.

The first step we’d need to take here is to get a raster which contains all of the rasters between 2 points. Since we can merge rasters with ST_Union we can run a query like the following.
SELECT ST_Union(rast)
FROM demelevation
WHERE ST_Intersects(rast, ST_SetSRID(ST_MakeLine(St_MakePoint(171, -43), St_MakePoint(171, -44)), 4326));
This will return a single column, single row result containing a raster with all tiles merged for a line between E171 degrees, S43 degrees and E171 degrees, S44 degrees. We now need to save that raster for processing so we can determine if there’s something along that line which will block our line of sight…

I came up with the following function which takes 2 geography parameters and returns true or false depending on if there is a line of sight between the 2 locations. Null is returns if there is no raster data and currently it's a bit undefined if there is partial raster data. Please note that the function currently does not take into account atmospheric refrations, which can have quite a big effect on objects near the horizon and may very well report things not to have a line of sight when they actually do. Currently I'm not quite sure how these should be calculated as most of the methods I've seen calculated for celestial bodies rather than objects on the face of the earth. I would imagine this also must take into account the distance of the object. If you have any ideas how I could implement this then please leave a comment.
CREATE OR REPLACE FUNCTION pano_is_point_visible_from(IN startloc GEOGRAPHY,
                                                      IN endloc GEOGRAPHY
) RETURNS BOOLEAN AS
$BODY$
-- This function calculates if there is a line of sight between 2 points.
-- It does this by analysing elevation data along the direct path towards
-- the destination point.
-- The comments in the function describe the process as if a person was standing
-- at the startloc (parameter) and was walking towards the endloc (parameter)
-- the walking process naturally involves steps. These steps are similar to
-- what the function does. It starts by finding the elevation at both the startloc
-- and the endloc and then calculates the pitch/angle of the line of sight.
-- The function then enters a loop, this is the walking loop, where we start
-- taking steps towards the endloc. After every step we calculate the pitch from
-- the starting location to the end location. If this pitch is ever higher or equal
-- to the pitch of the endloc then we know we cannot see the endloc from the startloc
-- as it's being obscured by our current location.
--
-- The function calculates these pitches using trig functions then it takes that
-- angle which has been calculated and subtracts the number of degrees around the
-- world that the object is away. It does this over a fixed sized sphere rather than
-- a complex spheoid. Please note that at this time atmospheric refraction is not
-- taken into account, this means that objects on the horizon could be miscalculated
-- by around half a degree! This means mountains in the distance will actually be
-- visibly slightly higher than they will be said to be by this function.

DECLARE elevationdata RASTER;
DECLARE tot_distance DOUBLE PRECISION;
DECLARE cur_distance DOUBLE PRECISION;
DECLARE bearing DOUBLE PRECISION;
DECLARE start_elevation DOUBLE PRECISION;
DECLARE end_elevation DOUBLE PRECISION;
DECLARE cur_elevation DOUBLE PRECISION;
DECLARE step_size DOUBLE PRECISION;
DECLARE curloc GEOGRAPHY;
DECLARE end_pitch DOUBLE PRECISION;
DECLARE cur_pitch DOUBLE PRECISION;

BEGIN
      -- This query builds a raster which contains all of the raster data
      -- between 2 points. We use ST_Makeline to create a line between our
      -- starting point and our destination. It is quite possible that we'll
      -- find no or just partial raster data between our 2 points. Later we
      -- do test to see if we got some and return NULL if we found no data.

      SELECT ST_UNION(rast) INTO elevationdata
      FROM demelevation e
      WHERE ST_Intersects(rast, ST_Makeline(CAST(startloc AS GEOMETRY), CAST(endloc AS GEOMETRY)));

      -- If we found no data at all then we can quit... At this
      -- point we have no idea if there is a line of sight, so we
      -- return NULL.

      IF elevationdata IS NULL THEN
            RAISE NOTICE 'No elevation data found.';
            RETURN NULL;
      END IF;

      -- We now set the elevation of our start point and our end point.
      -- Note that there currently is a bit of a fuzz factor here and I'm
      -- adding 2 metres to both these values. This is because at least for
      -- our start value our eyes are above the ground and not on the ground,
      -- so we'll have slightly more things in sight. For the end elevation
      -- this is not quite the case but the 2 metres was added due to the
      -- shapes of some mountains. If for example the mountain is completely
      -- flat at the top and we're standing in a location lower than it, if
      -- the summit location is marked in the middle of that flat area then
      -- we'll not be able to see it. I did not find this ideal as in reality
      -- I could see the mountain, just maybe not quite the middle of the summit,
      -- so the 2 meters being added to the end_elevation is fuzz factor, it
      -- perhaps should be more complex and be happy enough with seeing a point
      -- within X number of meters of the summit. At the time of writing this
      -- I could not decide what that value should be, so it remains like this.

      start_elevation := ST_Value(elevationdata, CAST(startloc AS GEOMETRY)) + 2;
      end_elevation := ST_Value(elevationdata, CAST(endloc AS GEOMETRY)) + 2;

      -- Now calculate the bearing which we must "walk" to
      -- our far off destination.
      bearing := ST_Azimuth(startloc, endloc);

      -- A variable to save the total distance we must walk.
      tot_distance := ST_Distance(startloc, endloc);

      -- Set our step size, smaller steps will mean more loops and slower to calculate.
      -- Also there is no point in going in smaller steps than the detail of the raster.
      -- This should match the raster resolution or be more than it for if performance
      -- is a problem.
      step_size = 30; -- metres

      -- We must now work out the pitch in degrees of our line of
      -- sight from our current location to the destination.
      -- Here we use atan which will give us a pitch, or angle on a triangle, since
      -- the earth is round we need to reduce the pitch by the number of degrees
      -- around the earth that the object is. We use a fixed radius for this which
      -- is not quite accurate but it will do for now. Variations caused by
      -- Atmospheric Refraction will likely cause much more variation than the shape
      -- of the planet.

      end_pitch := degrees(atan((end_elevation - start_elevation) / tot_distance)) - (tot_distance / (6370986 * pi() * 2) * 360);
 
      -- We now start a loop to walk to our destination.
      -- Note that we stop checking the distance when we're
      -- within step_size to the object, as there's no point in
      -- checking if we can see the object when we're standing
      -- on top of it.

      -- First we just need to take our first step...

      cur_distance := step_size;

      WHILE cur_distance <= (tot_distance - step_size) LOOP

            -- Now work out the location of our new step based on
            -- our starting location, the current distance we've
            -- travelled and the bearing to the destination.

            curloc := ST_Project(startloc, cur_distance, bearing);

            -- Now let's look at the elevation of the current location.
            cur_elevation := ST_Value(elevationdata, CAST(curloc AS GEOMETRY));

            --RAISE NOTICE 'start_elevation = %, end_elevation = %, cur_elevation = %, cur_distance = %, bearing = %',                   start_elevation, end_elevation, cur_elevation, cur_distance, degrees(bearing);

            -- Calculate the pitch to our current location, same as we did for
            -- the destination before the loop began.
            cur_pitch := degrees(atan((cur_elevation - start_elevation) / cur_distance)) - (cur_distance / (6370986 * pi() * 2) * 360);

            -- Now we simply check if the pitch to from our starting
            -- point to our current location is greater or equal to
            -- the pitch we calculated from the start point to the end
            -- point. If it is then we can't see the end location due
            -- to the current point appearing to be taller from the
            -- start point.

            IF cur_pitch >= end_pitch THEN
                  RAISE NOTICE 'Cannot see over object at pitch %. Pitch to destination is %, start elevation %, object elevation = %, distination elevation = %, dist from start = %, dist from end = %',
                        cur_pitch, end_pitch, start_elevation, cur_elevation, end_elevation, cur_distance, tot_distance - cur_distance;
                  RETURN FALSE;
            END IF;

            -- Now we can take another step then start do the whole process again...
            -- That is, providing we've not arrived at our destination yet.
            cur_distance := cur_distance + step_size;
      END LOOP;
      RETURN TRUE;
END;
$BODY$
  LANGUAGE plpgsql STABLE
  COST 1000;






We can now check if we have a line of sight by using the function like this:
SELECT pano_is_point_visible_from(
         ST_SetSrid(St_MakePoint(170.06488,-43.72071),4326), 
         ST_SetSrid(St_MakePoint(170.1420703,-43.594937),4326)
       );


Above I asked the function if it is possible to see the summit of Mount Cook from near mueller hut.
The function tells me that it is.

Now if I'm standing at the same spot, I know that in reality that I can't see Mount Tasman... So let's check if we're getting the correct results.

test=# select pano_is_point_visible_from(ST_SETSRID(St_MakePoint(170.06488,-43.72071),4326), ST_SetSrid(St_MakePoint(170.1572352,-43.5657091),4326));
NOTICE:  Cannot see over object at pitch 4.94936475078937. Pitch to destination is 4.83525382423895, start elevation 1815, object elevation = 3002, distination e
levation = 3458, dist from start = 13380, dist from end = 5384.461198757
 pano_is_point_visible_from
----------------------------
 f
(1 row)


Time: 64.390 ms

If we read the notice raised by the function we can see that we've hit land 13.38km from our starting point and the land we hit was at 3002 metres above sea level.

You can also see that the result was calculated fairly quickly at 64 milliseconds... Though if we need to calculate many points this is likely to become a problem. In the next blog I'll talk about how I optimised the line of slight calculations to cache results in a table. This is practical for my workload and improves performance around 300-400 times. http://davidrowley.blogspot.co.nz/2013/08/optimising-line-of-sight-calculations.html


Tuesday, 24 July 2012

Iceland Part 3



The next day the only rain I experienced was walking to the base of the waterfall.
Sometimes it’s hard to make the decision… Do I take off my motorbike gear or keep it on when going for walks… It’s sometimes a simple decision and sometimes impossible to know which is best. If it’s hot weather than it’s quite an easy decision, but when it’s cold then it seems to depend on how long the walk is. I’d take a wild guess that I use 4 times more energy walking with the motorbike gear on, but then I take up a lot of time taking it off and packing it away into the boxes on the bike. I sometimes feel like an old man when I walk with my motorbike gear on. I get tired so quickly, my legs overheat and I have to rest lots to cool down. I don’t feel out of breath, I just feel too hot. I’m glad it’s not a hot climate, but then if it was I’d have taken my gear off…. Probably…
There can’t be anywhere else in the world like it… Well, maybe I’ve just never been anywhere like it. I would ride for what seemed like ages but only make it a few kilometres. In and out, in and out. The Fjords made the travelling slow around here. Sometimes I’d ride 40 kilometres and only make a few kilometres in actual distance,  because I’d just ridding around to the other side other the fjord. But it’s not just once… this was happening all day, and all the next day. It really was slow going. When I travel like this I sometimes feel like it’s pointless. I’m just sitting on the bike all day looking at things passing by. I feel bad sometimes, I should be stopping and exploring, but then what could I see that I couldn’t see from the road? Well, I won’t know unless I stop!, but where should I stop? It’s all so amazing. 



Arnarfjörður in iceland


Dýrafjörður in iceland
Days later I came out of the area of the Western Fjords feeling like I had got the lay of the land. I now knew roughly what it looked like but I failed to feel like I had explored. I sometimes don’t mind that because it allows me to look at a map and then have a mental picture of what an area looks like, but then could I not do that by looking at pictures of the area on the internet? Maybe… but it’s not the same.
When the roads are quiet and the surface is good I always find myself passing the time by thinking about something other than riding the bike. Today I was starting to realise that my time in Iceland was running out. I really wanted to take a panoramic photo that summed the country up in 1 go. I tried to imagine what the photo would look like… Surely it would need to have a glacier in it… Oh and a volcano… I thought that was good as they go hand in hand in Iceland, but it will need something else since they do go hand in hand. I wondered what that thing was… I didn’t want it to be anything man made as the country cries out “Wild wild wild”. I wondered if it should be horses, then after a while decided that was a good idea… So I need to find a place with a glacier, volcano and some horses. I liked the idea… the horses would take up the foreground and the glacier and volcano the background. The problem was that I had already passed the area of Iceland where I could have probably got that photo, there were no glaciers where I was and the closest ones were too remote for there to be any fields with horses in them.
I was now feeling like I was starting to have deadlines again. I followed the main highway 1 east along the North side of the country all the way to an area called Myvatn. Tonight was the night I would finally fit my off road tyres, for tomorrow I’m doing my first real off road in Iceland. I now had mentally planned out each day that was left in my trip and I had set myself a strict face paced schedule to keep until I got on the ferry.


Horses Near Myvatn in iceland
I found a camp next the Myvatn late and set up my tent. Once my tent was up my bike was hauled onto the centre stand again and the back wheel was removed and the tyre was let down. Ever since my days of travelling bike motorbike in Australia I’ve been self-sufficient with tyres. I always fit my own tyres and I always fix my own punctures. I always carry tyre leavers, patches, spare tubes and a pump. I wouldn’t say I’m amazing at fitting them as I always struggle at lining the inner tube valve up with the hole in the rim while trying to give myself room for my fingers with the tyre levers. 1 hour and 15 minutes later my bike was looking extra mean with brand new off road tyres. I was now excited and couldn’t wait for tomorrow to come!


The following day was pretty fast paced. I was at the top of a volcano, or more accurately a cinder cone looking over the lake, Myvatn. Then a bit later I was looking mud pools and volcanic vents forcing stream up out into the atmosphere while trying not to gag at the awful sulphur smell, before I knew it I was standing at mightiest waterfall that I’ve ever seen. (I later learned it was likely Europe’s most powerful). By late evening I was behind in my schedule. I worked out that I needed to double back to Myvatn to get fuel as I had wasted enough to put me in danger of running out before the next time I could get fuel. This set me back a fair bit. I had planned to be as close as I could get to a place called Askja.


Hverfjall in iceland
My bike was now fully fuelled up, probably quite dangerously I even had filled up the part of the tank that is meant to allow the fuel to expand on a hot day… But I didn’t expect any of those so I put fuel there instead and headed East. I pulled off the highway into the turn off for road F88. The “F” means it’s for four wheel drives only. I stopped the bike and started reading the array of signs that had been put up with information about the road. No hire cars allowed, I got that… But I wanted information about any river crossings on the road, I then found a sign for that, it showed me where they all were, but I had no idea how deep they would be.
It had been a while since I had been on rough roads with a motorbike. I felt out of my depth riding this heavy bike up this badly corrugated track. I was introduced to these “Corrugations” when I was 20 years old when I was riding my motorbike Cape York in the very North of Australia. Ok, so you might ask…. What are they?  Well, think of walking along a sandy beach at low tide and seeing the ripples in the sand that the sea left as it went out, or think of an old fashioned washboard that was used to scrub clothes clean. Basically on gravel roads, sandy roads, or clay roads it’s possible for a similar thing to form. The corrugations are always run left to right along the width of the road, so riding down the road means riding over the corrugations. The size of them varies wildly where sometimes they’re small enough not to notice, and sometimes riding over them is almost impossible. The corrugations I found on F88 I found were more towards the impossible end of the scale. Normally I keep my map neatly tucked in between the seat and petrol tank the corrugations soon made that disappear. I had to stop and drop me tyre pressures down to try to flatten the tyre enough to not go as deep into them and soften the blow when I hit the peaks of the next one. Speed is an issue, going slowly enough to not get the vibration means you’ll be going slower than walking speed and if you go faster than 50 mph (80km/h) you can start to skip over them. The problem with that is that the tyres are not 100% on the ground all the time and steering gets to be a problem sometimes.
An hour or so down the track the corrugations were starting to feel more normal. It made me remember about how my own standards of a track would change wildly depending on what I had been riding over before I got to the track, and since I had just come from a nice highway onto this track then it’s no wonder I thought it was rough. If I had come off a track with deep rutted soft sand then I’d probably have thought this was easy!
The first of the river crossings didn’t slow me down too much. I parked the bike a few metres from the edge and jumped off. I had bought some black bin bags when I filled up with fuel. I had seen a man on a motorbike about a week before who had the remains of some bin bags around his legs… The idea clicked at the time, I thought it would be a great way of making temporary waders to walk into deep water with without getting my legs wet. I unrolled 2 bags from the roll, one for each leg and walked into the water holding onto one with each hand so they didn’t fall down to my ankles. My feet were soaked within seconds as the small stones pierced their way into the bags. The water was not too deep and the bottom was not too rough. I walked back to the bike and carefully rode it into the river. The water came over the foot rests but it didn’t bother me as my feet were already wet. The water was nowhere near as cold as I’d have imagined it would have been either!
It was getting late by this time. I didn’t see any other traffic on the road. It made the whole thing feel like a bit more of an adventure. I always find it disappointing when I’m travelling somewhere that I think is remote then when I arrive I find there is 100’s of people already there… I remembering when I had travelled with my motorbike in Australia, I had made it to a waterfall called Mitchell Falls which is in a remote area in the Kimberley region of Western Australia, I parked the bike up next to 2 4 wheel drives, which were the only 2 in site and walked the 3 kilometres to the falls only to find over 100 people sitting in a pool at the top of the falls… It didn’t add up… 2 4 wheel drives with 100 people?? It turned out a cruise ship was off the coast and all these people were brought in via helicopter.
I soon came to another river crossing. It was now passed 10pm and I thought there was probably no chance that I’d meet other traffic on this track. I once again stopped the bike before the edge of the river, this time I didn’t bother with the black bags, I just walked right in. In the middle the water was almost at the level where men think twice to go any deeper, especially in Iceland. This time the water was cold, I was uncontrollably making screeching noises at the cold! I thought that it must be fresh glacial melt water as it felt like it was bearly above freezing. I found that if I walked down river a little that the water was a bit more shallow. It would have been crazy to try and cross in the middle as the water would have come over the motorbike’s seat and dropping it in that depth would have given me massive problems, especially since it was likely nobody would come to my aid at that time of night. Downriver the water was just over knee deep, which I remembered to be just over 60cm from my days in Australia. I knew that was about my limit for my old Yamaha Tenere, but I’d never taken my Africa Twin into water anywhere near this deep before. I thought maybe I should camp and see if the water was any lower in the morning, It’s quite common for rivers with glacial melt water to be high at the end of the day as the glaciers melt much more in the day than at night. A sign quite clearly stated I was not allowed to camp. But not through wanting to obey the sign I decided to continue and see what happens… After all if anything was to go wrong, then it would “all just be part of the adventure”.
I jumped on the bike, started the engine and slowly let go of the clutch lever. The front wheel was about completely under the water, as the back made it to the same depth I could feel my panniers dragging in the water. I kept the revs steady but kept my hand on the clutch just a little so if I hit anything under the water I wouldn’t stall the engine, doing this also let me ride a bit slower. The back wheel started to spin in the soft gravel riverbed and the bike, though it didn’t stop moving dug its way in a little deeper under the water. Just as I was at the stage of panic that I was going to be stuck in the middle, the bike started to rise out of the other side….. front wheel out... back wheel out… cough! And the engine just died.
I was now freezing! That water was much colder than the first river I crossed. I was at the stage of not being able to think clearly, taking badly thought out risks, the whole idea of crossing at this time of night was a badly thought out idea. I could have camped and waited for the first 4 wheel drive in the morning to watch me cross and help tow the bike out if I dropped it or drowned the engine. But instead now I was sitting with the back wheel barely out the water with a bike that just stopped running. All this went through my head in about a millisecond as that one millisecond later I had pressed the start button and the bike burst into life again, I gave it a rev and let go the clutch and wheel span all the way up the far side back onto the level ground again. Phew!