Walking Trip …

Walking Trip

Walking Trip

Offenbach's Suite ... Warts 'n All

Offenbach's Suite ... Warts 'n All

If this was interesting you may be interested in this too.

Posted in Photography, Trips | Tagged , , | 34 Comments

Screenshot Annotating in iOS Primer Tutorial

Screenshot Annotating in iOS Primer Tutorial

Screenshot Annotating in iOS Primer Tutorial

In a similar line of thinking to yesterday’s Email iOS Vignette Primer Tutorial we feature, today iPhone and iPad (ie. iOS) …


Screenshot Annotating

on the way among …

  • screenshot (whatever currently appears on your iOS screen) via Home button + Increase Volume (or “Side”) button (iPhone) or Home button + “Top” button (iPad) simultaneously (and quickly) on iPhone or iPad
  • tap bottom left Photo icon
  • perform some Screenshot Annotating (via use of various pens and colour selection icons presented down the bottom of presented Photo (you screenshotted)
  • that can then be saved to Photos (app) via Done link or Shared immediately via Share icon

It’s really apt functionality, because, presumably, you went to the effort to screenshot for a good reason you might want to explain about, to a sharing recipient. We used it for the tutorial picture featuring in Landing Page WordPress Tags Primer Tutorial. And they say …

A picture tells a thousand words

Today’s animated GIF presentation shows you some of this functionality in action!


Previous relevant Email iOS Vignette Primer Tutorial is shown below.

Email iOS Vignette Primer Tutorial

Email iOS Vignette Primer Tutorial

Pretty obviously, its’s not just your more sophisticated graphical editors, as with Gimp Vignette Primer Tutorial that are capable of vignetting a photograph, the example task for today’s tutorial.

For your iOS mobile devices like the iPad and iPhone, on the way to sharing that photograph, and today’s tutorial title dedicates itself to the idea of Email Sharing, but there are many more Sharing options than Email with iOS mobile devices. These days, on the way to that Sharing with recent iOS versions you will see an “Edit” link or “Edit Photo” link that can take you to an image editor on the way through to Sharing, meaning that …

  1. tap Camera icon
  2. set Photo mode
  3. take photo with round white button click
  4. tap the “Photo taken” icon
  5. tap “Edit” link
  6. edit your photo … and today’s work is the last one … Vignette 100% … as shown in today’s PDF presentation
  7. tap “Done” link
  8. choose a Sharing option such as Email to continue sharing your Adjusted photo with someone
  9. … to edit and fix on the run! After all, you can join the …


    Everyone's a critic

    … crowd, but get in ahead of the game, being your own critic before others do?! Cute functionality, huh?!

    The iOS edit options for iOS 13.7 are …

    • Auto
    • Exposure
    • Brilliance
    • Highlights
    • Shadows
    • Contrast
    • Brightness
    • Black Point
    • Saturation
    • Vibrance
    • Warmth
    • Sharpness
    • Definition
    • Noise Reduction
    • Vignette

    … and we’ll leave you with a before and after (vignette) of Nala …

    Before After


    Previous relevant Gimp Vignette Primer Tutorial is shown below.

    Gimp Vignette Primer Tutorial

    Gimp Vignette Primer Tutorial

    The last time we talked about the miraculous, redolent and amazing image editor called Gimp am sure there was someone in a shower … it stands to reason … and one of those showerers, surely, would have been singing The Gimp Song … and if not … why not? … but we digress … anyway we had the Gimp Transparency Primer Tutorial as shown below go into some image transparency issues with Gimp.

    In today’s tutorial we make use of a great tutorial (even so far as with direct quotes below) called Add a Vignette to a Photograph with GIMP (thanks) to try a photographic technique called vignetting on one of the photographs we added, recently, into the mix of those of the Custom Header Image mix at this blog … specifically the one of Nala, the dog, on the door ledge. Need to warn you here and now that if there was the time all over again, it would be better achieved that second time around, but this is not the point with learning, but rather getting some starting point with a great “product” like Gimp, and trying it yourself, once you have a method. It boils down to:

    1. Open Gimp graphical editor application
    2. File->Open … pick your image file
    3. Layer->New Layer (we’ll call “Vg”) … pick Foreground Colour
    4. In the Layers dialog, click on your “Vg” layer to select it, and select Soft light from the “Mode” drop-down box
    5. Right click on your “Vg” layer and go to Add Layer Mask. In the dialog that pops up, you want “Initialise Layer Mask to” set to “White (full opacity)”. Click “Add”
    6. Below Opacity bar select Link icon next to Eye icon, which will already be showing
    7. Use the freeform select tool (press F to bring this up) and draw a selection somewhere around the primary point of interest in your photo
    8. Use your bucket tool (Shift+B) and click within the selection to fill it
    9. Deselect your selection with Select->None
    10. Go to Filters->Blur->Gaussian Blur. In the dialog that comes up, you want “Radius” set to a very large amount; a tenth of the longest edge of the photo is not too much
    11. Click on your “Vg” layer to select it (if it isn’t already selected), and then slide the opacity slider towards the right until the effect is subtle enough. Our (ever so subtle) example of Nala, in the tutorial, used an opacity of about 66%
    12. Click Export button in two windows (NB. this overwrites the image file, so if this is not desirable, export to a different image file name and/or type)

    Here is an image comparison link.

    As with most Gimp ideas, jump in and give it a go, as you’ll find your own ways and means of using this great product … am pretty sure.

    Link to Gimp “spiritual home” … here.
    Link to Gimp forum … here.


    Previous relevant Gimp Transparency Primer Tutorial is shown below.

    Gimp Transparency Primer Tutorial

    Gimp Transparency Primer Tutorial

    Here is a tutorial that adds to a previous Gimp Layers Primer Tutorial as shown below, and gives you more insight into the massive possibilities of using a sophisticated image editor and use layers with various amounts of transparency, especially suited to use with png image files.

    Today’s tutorial where we construct a Birthday Card that needs tweaking for the words in front to be seen a bit more clearly, by making the image behind a bit more transparent, changes the transparency of a single image via:

    1. Open Gimp graphical editor application
    2. File->Open Layers … pick your image file
    3. If Layers window not showing, make it show via Windows->Layers – Brushes
    4. Below Opacity bar select Link icon next to Eye icon, which will already be showing
    5. Change Opacity bar setting to a value of Transparency (100% is Opaque, 0% is Transparent) that suits … today we do 70%
    6. File->Export
    7. Click Export button in two windows (NB. this overwrites the image file, so if this is not desirable, export to a different image file name and/or type)

    As with most Gimp ideas, jump in and give it a go, as you’ll find your own ways and means of using this great product … am pretty sure.

    Link to Gimp “spiritual home” … here.
    Link to Gimp forum … here.


    Previous relevant Gimp Layers Primer Tutorial is shown below.

    Gimp Layers Primer Tutorial

    Gimp Layers Primer Tutorial

    Here is a tutorial that gives you an insight into the massive possibilities of using a sophisticated image editor and use layers with various amounts of transparency, especially suited to use with png image files.

    Transparency (or its obverse, opacity) can be used to have the one image achieve several “ends” (ie. purposes). Although it is a bit of a clumsy example in the tutorial, you can see that the technique can be used for artistic purposes … often called “Photoshopping” (named after the more famous, and also brilliant, rival product, Photoshop).

    Lots of those classic “Photoshopping” techniques can be achieved in Gimp, and some other tutorials at this blog touch on that.

    Am sure you can imagine what the concept of a layer is with regard to image manipulation. Within Gimp, for beginners not used to this concept, you find yourself underestimating and underplaying what can be achieved with the various layers of a multi-layered image. In simplistic terms each layer has the functionality in Gimp to be treated as a whole new image, and this is the best way to think of it when trying to achieve what you want to achieve with Gimp.

    Link to Gimp “spiritual home” … here.
    Link to Gimp forum … here.

    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.

Posted in eLearning, iOS, Tutorials | Tagged , , , , , , , , , , | Leave a comment

Email iOS Vignette Primer Tutorial

Email iOS Vignette Primer Tutorial

Email iOS Vignette Primer Tutorial

Pretty obviously, its’s not just your more sophisticated graphical editors, as with Gimp Vignette Primer Tutorial that are capable of vignetting a photograph, the example task for today’s tutorial.

For your iOS mobile devices like the iPad and iPhone, on the way to sharing that photograph, and today’s tutorial title dedicates itself to the idea of Email Sharing, but there are many more Sharing options than Email with iOS mobile devices. These days, on the way to that Sharing with recent iOS versions you will see an “Edit” link or “Edit Photo” link that can take you to an image editor on the way through to Sharing, meaning that …

  1. tap Camera icon
  2. set Photo mode
  3. take photo with round white button click
  4. tap the “Photo taken” icon
  5. tap “Edit” link
  6. edit your photo … and today’s work is the last one … Vignette 100% … as shown in today’s PDF presentation
  7. tap “Done” link
  8. choose a Sharing option such as Email to continue sharing your Adjusted photo with someone
  9. … to edit and fix on the run! After all, you can join the …


    Everyone's a critic

    … crowd, but get in ahead of the game, being your own critic before others do?! Cute functionality, huh?!

    The iOS edit options for iOS 13.7 are …

    • Auto
    • Exposure
    • Brilliance
    • Highlights
    • Shadows
    • Contrast
    • Brightness
    • Black Point
    • Saturation
    • Vibrance
    • Warmth
    • Sharpness
    • Definition
    • Noise Reduction
    • Vignette

    … and we’ll leave you with a before and after (vignette) of Nala …

    Before After


    Previous relevant Gimp Vignette Primer Tutorial is shown below.

    Gimp Vignette Primer Tutorial

    Gimp Vignette Primer Tutorial

    The last time we talked about the miraculous, redolent and amazing image editor called Gimp am sure there was someone in a shower … it stands to reason … and one of those showerers, surely, would have been singing The Gimp Song … and if not … why not? … but we digress … anyway we had the Gimp Transparency Primer Tutorial as shown below go into some image transparency issues with Gimp.

    In today’s tutorial we make use of a great tutorial (even so far as with direct quotes below) called Add a Vignette to a Photograph with GIMP (thanks) to try a photographic technique called vignetting on one of the photographs we added, recently, into the mix of those of the Custom Header Image mix at this blog … specifically the one of Nala, the dog, on the door ledge. Need to warn you here and now that if there was the time all over again, it would be better achieved that second time around, but this is not the point with learning, but rather getting some starting point with a great “product” like Gimp, and trying it yourself, once you have a method. It boils down to:

    1. Open Gimp graphical editor application
    2. File->Open … pick your image file
    3. Layer->New Layer (we’ll call “Vg”) … pick Foreground Colour
    4. In the Layers dialog, click on your “Vg” layer to select it, and select Soft light from the “Mode” drop-down box
    5. Right click on your “Vg” layer and go to Add Layer Mask. In the dialog that pops up, you want “Initialise Layer Mask to” set to “White (full opacity)”. Click “Add”
    6. Below Opacity bar select Link icon next to Eye icon, which will already be showing
    7. Use the freeform select tool (press F to bring this up) and draw a selection somewhere around the primary point of interest in your photo
    8. Use your bucket tool (Shift+B) and click within the selection to fill it
    9. Deselect your selection with Select->None
    10. Go to Filters->Blur->Gaussian Blur. In the dialog that comes up, you want “Radius” set to a very large amount; a tenth of the longest edge of the photo is not too much
    11. Click on your “Vg” layer to select it (if it isn’t already selected), and then slide the opacity slider towards the right until the effect is subtle enough. Our (ever so subtle) example of Nala, in the tutorial, used an opacity of about 66%
    12. Click Export button in two windows (NB. this overwrites the image file, so if this is not desirable, export to a different image file name and/or type)

    Here is an image comparison link.

    As with most Gimp ideas, jump in and give it a go, as you’ll find your own ways and means of using this great product … am pretty sure.

    Link to Gimp “spiritual home” … here.
    Link to Gimp forum … here.


    Previous relevant Gimp Transparency Primer Tutorial is shown below.

    Gimp Transparency Primer Tutorial

    Gimp Transparency Primer Tutorial

    Here is a tutorial that adds to a previous Gimp Layers Primer Tutorial as shown below, and gives you more insight into the massive possibilities of using a sophisticated image editor and use layers with various amounts of transparency, especially suited to use with png image files.

    Today’s tutorial where we construct a Birthday Card that needs tweaking for the words in front to be seen a bit more clearly, by making the image behind a bit more transparent, changes the transparency of a single image via:

    1. Open Gimp graphical editor application
    2. File->Open Layers … pick your image file
    3. If Layers window not showing, make it show via Windows->Layers – Brushes
    4. Below Opacity bar select Link icon next to Eye icon, which will already be showing
    5. Change Opacity bar setting to a value of Transparency (100% is Opaque, 0% is Transparent) that suits … today we do 70%
    6. File->Export
    7. Click Export button in two windows (NB. this overwrites the image file, so if this is not desirable, export to a different image file name and/or type)

    As with most Gimp ideas, jump in and give it a go, as you’ll find your own ways and means of using this great product … am pretty sure.

    Link to Gimp “spiritual home” … here.
    Link to Gimp forum … here.


    Previous relevant Gimp Layers Primer Tutorial is shown below.

    Gimp Layers Primer Tutorial

    Gimp Layers Primer Tutorial

    Here is a tutorial that gives you an insight into the massive possibilities of using a sophisticated image editor and use layers with various amounts of transparency, especially suited to use with png image files.

    Transparency (or its obverse, opacity) can be used to have the one image achieve several “ends” (ie. purposes). Although it is a bit of a clumsy example in the tutorial, you can see that the technique can be used for artistic purposes … often called “Photoshopping” (named after the more famous, and also brilliant, rival product, Photoshop).

    Lots of those classic “Photoshopping” techniques can be achieved in Gimp, and some other tutorials at this blog touch on that.

    Am sure you can imagine what the concept of a layer is with regard to image manipulation. Within Gimp, for beginners not used to this concept, you find yourself underestimating and underplaying what can be achieved with the various layers of a multi-layered image. In simplistic terms each layer has the functionality in Gimp to be treated as a whole new image, and this is the best way to think of it when trying to achieve what you want to achieve with Gimp.

    Link to Gimp “spiritual home” … here.
    Link to Gimp forum … here.

    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.


    If this was interesting you may be interested in this too.

Posted in eLearning, iOS, Photography, Tutorials | Tagged , , , , , , , , , , , , , | Leave a comment

HTML and Javascript and CSS Survey Traverse SVG Class Tutorial

HTML and Javascript and CSS Survey Traverse SVG Class Tutorial

HTML and Javascript and CSS Survey Traverse SVG Class Tutorial

Adding to the progress of yesterday’s HTML and Javascript and CSS Survey Traverse Interactive Input Tutorial we turn back to the burgeoning methodologies used in HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial by extending our …


SVG class

… emoji text styling possibilities that can simulate text flip and text flop. Yes, that Google Chart Geo Chart by Google design uses SVG (Scalable Vector Graphics) heavily. And luckily, that SVG can be styled, not for all CSS that we’ve tried (eg. glow work) but SVG text graphics can be helped out by the CSS writing-mode property allowing additions (to the CSS font-size properties) to our HTML’s Javascript array as per


var classesare=['wmrl','wmlr','wmtb','border','bcoly','cglow','glow','xxsmall','xsmall','xx-small','x-small','smaller','small','xxlarge','xlarge','xx-large','x-large','larger','large','tenp','twentyp','onefiftyp','fiftyp','twohundredp','threehundredp','fourhundredp','fivehundredp','sixhundredp','zero','one','two','three','four','five','six','seven','eight','nine','dot'];

… and in the Geo Chart interfacing PHP you now can get an SVG text graphic like …


<text x="883.3403011787676" y="519.1186730412636" data-r="9" data-stroke="#cccccc" data-stroke-width="1" onclick="gck(0);" title="one " data-fill="url(#attachedImage0)" class="wmlr xxlarge">🏂</text>

… calling on Geo Chart interfacing PHP styling …

<style>


.border { border: 1px solid blue; }

.bcoly { background-color: yellow; }


.wmrl { writing-mode:vertical-rl; }


.wmlr { writing-mode:vertical-lr; }


.wmtb { writing-mode:horizontal-tb; }


.xxsmall { font-size:xx-small; }
.xsmall { font-size:x-small; }
.small { font-size:small; }
.medium { font-size:medium; }
.large { font-size:large; }
.xlarge { font-size:x-large; }
.xxlarge { font-size:xx-large; }
.smaller { font-size:smaller; }
.larger { font-size:larger; }


.tenp { font-size:10%; }
.twentyp { font-size:20%; }
.fiftyp { font-size:50%; }
.onefiftyp { font-size:150%; }
.twohundredp { font-size:200%; }
.threehundredp { font-size:300%; }
.fourhundredp { font-size:400%; }
.fivehundredp { font-size:500%; }
.sixhundredp { font-size:600%; }

.glow {
-webkit-animation: glow 1s ease-in-out infinite alternate;
-moz-animation: glow 1s ease-in-out infinite alternate;
animation: glow 1s ease-in-out infinite alternate;
}

@-webkit-keyframes glow {
from {
box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #e60073, 0 0 9px #e60073, 0 0 11px #e60073, 0 0 13px #e60073, 0 0 15px #e60073;
}

to {
box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #ff4da6, 0 0 10px #ff4da6, 0 0 12px #ff4da6, 0 0 14px #ff4da6, 0 0 16px #ff4da6;
}
}

.cglow {
box-shadow-bottom-right-radius: 50%;
box-shadow-bottom-left-radius: 50%;
box-shadow-top-right-radius: 50%;
box-shadow-top-left-radius: 50%;
-webkit-animation: cglow 1s ease-in-out infinite alternate;
-moz-animation: cglow 1s ease-in-out infinite alternate;
animation: cglow 1s ease-in-out infinite alternate;
-webkit-border-radius: 50%;
border-radius: 50%;
}

@-webkit-keyframes cglow {
from {
box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #e60073, 0 0 9px #e60073, 0 0 11px #e60073, 0 0 13px #e60073, 0 0 15px #e60073;
box-shadow-bottom-right-radius: 50%;
box-shadow-bottom-left-radius: 50%;
box-shadow-top-right-radius: 50%;
box-shadow-top-left-radius: 50%;
}

to {
box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #ff4da6, 0 0 10px #ff4da6, 0 0 12px #ff4da6, 0 0 14px #ff4da6, 0 0 16px #ff4da6;
box-shadow-bottom-right-radius: 50%;
box-shadow-bottom-left-radius: 50%;
box-shadow-top-right-radius: 50%;
box-shadow-top-left-radius: 50%;
}
}

</style>

… and, as you can see, we live in hope of getting “glow” CSS to work with SVG text one day!

The user can make this Geo Chart CSS writing-mode styling happen via what they enter into the Placenames textbox which now has the non-mobile advice (on hovering) …

Geo Chart emoji SVG class styling suffixes (wmlr) or (wmrl) or (wmtb) for CSS styling writing-mode:vertical-lr; writing-mode:vertical-rl; writing-mode:horizontal-tb; respectively

A further retweaked geo_chart.php Geo Chart interfacer as called by the modified “last changed” SurveyTraverse.htm Geo Chart calling live run link with improved Emoji CSS styling possibilities akin to flip and flop, is, again, worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse Interactive Input Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Interactive Input Tutorial

HTML and Javascript and CSS Survey Traverse Interactive Input Tutorial

There is a vast difference to the complexity of web applications that …

  • just impart information (in a broadcasting style) … versus ones that …
  • accept interactive user input as a variable to then impart information that differs depending on those user entries

… and pretty obviously the latter one above presents many more challenges than the former. Yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial (and today’s) web application is an example where there is a great deal of interactive user entry offered.

You will find coding and deploying such web applications there are categories of users, from those who try to avail themselves of all the “bells and whistles” available right through to those who just get their kicks trying to make it fail. A common interactive entry feature that benefits from a bit of planning is your HTML input type=text textbox. Do you think of emojis as text? Well, they are, and often we don’t cater for emoji data entered into textboxes unless there is considerable “follow through” on the web application. Today’s web application has us using a five iron on a par four.

We have two scenarios we can think of that catering for interactively entered emoji characters (on macOS, using the control-command-space key sequence) …

  • in first Javascript prompt window (as a chance for user to define a default Geo Chart emoji (which can be none))
  • in Placename textbox (anywhere) as a specific Emoji definition for a particular Survey Traverse station (or point)

So what is the mechanism to share these new settings between calls of the web application? We’ve decided to use hashtag # navigation, because we are only dealing with top level (client) HTML/Javascript/CSS with this web application (rather than serverside PHP). Did you know you can string along hashtag concepts as per …


#DefaultEmojiCodePoint#GeoChartWidth#GeoChartHeight

… those interim # above still appearing within …


location.hash

… and so being quite a useful alternative “settings imparting tool” but not as good as (the “GET”) ? and & arguments, because caching does not recognize a changed location.hash as it does a changed document.URL (URL).

Our changed SurveyTraverse.htm Geo Chart (1000 x 630) calling live run via DMS geographicals with no Emojis link is worth mulling over.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial

Supposing you’re a crow setting out on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial‘s …

  • Australian Capital Cities trip …
  • stopping off at each city to take a break … and …
  • you want to know which direction to head … and …
  • how far away is the next city

… well, we’re here to help, thanks to the advice at this very useful link to calculate …

  • First Azimuth (ie. first bearing you head off with, noting that this bearing changes as the trip goes on) …

    function doazimuthgcd() { // thanks to https://www.movable-type.co.uk/scripts/latlong.html
    // dE0 (has E0 longitude and N0 latitude),dE1 etc dN0,dN1 etc
    // Formula: θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
    // where φ1,λ1 is the start point, φ2,λ2 the end point (Δλ is the difference in longitude)
    var kjw=0, kkjw=1;
    var thisaz=0.0, deltalong;
    var sparec=document.getElementById('tde').innerHTML;
    if (document.getElementById('tde').innerHTML.indexOf('ongitude') != -1 && document.getElementById('tde').innerHTML.indexOf(' (') != -1) {
    document.getElementById('tde').innerHTML=sparec.replace(' (',' (<font color=blue>').replace(')',')</font>');
    sparec=document.getElementById('tdn').innerHTML;
    document.getElementById('tdn').innerHTML=sparec.replace(' (',' (<font color=blue>').replace(')',')</font>');
    sparec=document.getElementById('diffe').innerHTML;
    document.getElementById('diffe').innerHTML='<font color=blue>First Azimuth / </font>' + sparec;
    sparec=document.getElementById('diffn').innerHTML;
    document.getElementById('diffn').innerHTML='<font color=blue>Great Circle Distance / </font>' + sparec;
    while (document.getElementById('dE' + kjw)) {
    deltalong=eval(eval(eval('' + document.getElementById('E' + kkjw).value) - eval('' + document.getElementById('E' + kjw).value)) * eval(Math.PI / 180.0));
    // Formula: θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
    thisaz=
    eval('' +
    Math.atan2(
    eval(
    Math.sin(deltalong) *
    Math.cos(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0)))
    ),
    eval(
    eval(
    Math.cos(eval(eval('' + document.getElementById('N' + kjw).value) * eval(Math.PI / 180.0))) *
    Math.sin(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0)))) -
    eval(
    Math.sin(eval(eval('' + document.getElementById('N' + kjw).value) * eval(Math.PI / 180.0))) *
    Math.cos(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0))) *
    Math.cos(deltalong))
    )
    )) * eval(180.0 / Math.PI);
    if (thisaz < 0.0) { thisaz+=360.0; }
    document.getElementById('dE' + kjw).className='fatd';
    document.getElementById('dE' + kjw).innerHTML='' + thisaz + '';
    document.getElementById('dE' + kjw).title=dechange(document.getElementById('dE' + kjw).innerHTML, kjw, numlegs);
    document.getElementById('dN' + kjw).innerHTML='<font color=blue>' + great_circle_distance(eval('' + document.getElementById('E' + kjw).value), eval('' + document.getElementById('N' + kjw).value), eval('' + document.getElementById('E' + kkjw).value), eval('' + document.getElementById('N' + kkjw).value)) + '</font>';
    kjw++;
    kkjw++;
    }
    //document.title+=' ... ' + kjw;
    }
    }
  • Great Circle Distance …

    function great_circle_distance(talis, gnolis, latis, longis) {
    var ourdist=0.0;
    var rgnol=eval((gnolis) * Math.PI / 180.0);
    var rtal=eval((talis) * Math.PI / 180.0);
    var rlong=eval((longis) * Math.PI / 180.0);
    var rlat=eval((latis) * Math.PI / 180.0);
    var deltalong = Math.abs(eval(((gnolis)-(longis)) * Math.PI / 180.0));
    var acof = eval(Math.sin(rtal) * Math.sin(rlat)) + (Math.cos(rtal) * Math.cos(rlat) * Math.cos(deltalong)); // via //en.wikipedia.org/wiki/Great-circle_distance ... thanks
    //ourdist = eval(Math.round((Math.acos(acof) * 6371000.0) + 0.00001) * 100) / 100;
    ourdist = eval((Math.acos(acof) * 6371000.0) + 0.00001);
    return ourdist;
    }

… that now gets incorporated into our changed SurveyTraverse.htm Geo Chart calling live run via DMS geographicals link.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

Up to and including yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial‘s web application’s CSV co-ordinate formats supported included …

  • grid Easting and Northing co-ordinates
  • geographical Latitude and LongitudeLongitude and Latitude decimal co-ordinates … and today we add onto that list …
  • geographical Latitude and LongitudeLongitude and Latitude DMS (degrees, minutes, seconds) co-ordinates

… that latter format popular with Wikipedia‘s geodata content, and many other sources too. We took some such Wikipedia content for Australia’s capital cities and fed it into a Sydney.csv

“31°57′8″S”,”115°51′32″E”,”Perth”
“34°55′44″S”,”138°36′4″E”,”Adelaide”
“12°26′17″S”,”130°50′28″E”,”Darwin”
“27°28′04″S”,”153°01′41″E”,”Brisbane”
“33°51′54″S”,”151°12′34″E”,”Sydney”
“35°17′35″S”,”149°07′37″E”,”Canberra”
“37°48′49″S”,”144°57′47″E”,”Melbourne”
“42°52′50″S”,”147°19′30″E”,”Hobart”

… and onto an execution using such DMS geographicals above …

… possible because of a new PHP function …

<?php

function dmscheck($inct) {

// "33°51′54″S","151°12′34″E","Sydney"
// "34°55′44″S","138°36′4″E","Adelaide"
$lathfound=false;
$longhfound=false;
$restb="";
$degstrone="";
$reststrone="";
$degstrtwo="";
$reststrtwo="";
$minstr="";
$isdms=false;
$secstr="";
$nextrestb="";
$minusstr="";
$hdrline="";
$spares="";
$ideg=-1;
$lastc="";
$outct=$inct;
$outbits=explode("°", $inct);
if (strpos(strtolower($outbits[0]), "latitude") !== false && strpos(strtolower($outbits[0]), "longitude") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "latitude") < strpos(strtolower($outbits[0]), "longitude")) {
$lathfound=true;
} else {
$longhfound=true;
}
} else if (strpos(strtolower($outbits[0]), "lat") !== false && strpos(strtolower($outbits[0]), "long") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "lat") < strpos(strtolower($outbits[0]), "long")) {
$lathfound=true;
} else {
$longhfound=true;
}
}


if (sizeof($outbits) <= 2 && $isdms) {
$outct=str_replace(".0", "°0", str_replace(".1", "°1", str_replace(".2", "°2", str_replace(".3", "°3", str_replace(".4", "°4", str_replace(".5", "°5", str_replace(".6", "°6", str_replace(".7", "°7", str_replace(".8", "°8", str_replace(".9", "°9", $inct))))))))));
$outbits=explode("°", $outct);
$outct=$inct;
}


if (sizeof($outbits) > 2) {


$reststrone=strtoupper(explode(",", $outbits[1])[0]);
$minusstr="";
if (strpos(strtoupper($reststrone), "W") !== false || strpos(strtoupper($reststrone), "S") !== false) {
$minusstr="-";
}
//echo "\n \$reststrone=" . $reststrone . " \$minusstr=" . $minusstr . "\n";
//$reststrtwo=strtoupper(explode(",", $outbits[1])[0]);
if (!$lathfound && !$longhfound) {
while (substr($outbits[0], $ideg, 1) <= '9' && substr($outbits[0], $ideg, 1) >= '0') {
//echo "substr(\$outbits[0], \$ideg, 1)=" . substr($outbits[0], $ideg, 1) . "\n";
$spares=$degstrone;
$degstrone=substr($outbits[0], $ideg, 1) . $spares;
$ideg--;
}
$ideg=-1;
while (substr($outbits[1], $ideg, 1) <= '9' && substr($outbits[1], $ideg, 1) >= '0') {
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1], $ideg, 1) . $spares;
$ideg--;
}
if (strpos($reststrone, "N") !== false || strpos($reststrone, "S") !== false) {
if ($degstrone <= 90.0) {
$hdrline="Latitude,Longitude,\n";
}
}
}


$outct=substr($outbits[0],0,(strlen($outbits[0]) - strlen($degstrone))) . $minusstr . $degstrone;
for ($iuyt=1; $iuyt<sizeof($outbits); $iuyt++) {

$minusstr="";
$restb=explode(",", $outbits[$iuyt])[0];
$nextrestb="";
if (sizeof($outbits) > (1 + $iuyt)) {
$nextrestb=explode(",", $outbits[1 + $iuyt])[0];
}
//echo "\n\$restb=" . $restb . "\n<br>";
$minstr="";
$secstr="";
$ideg=0;
if (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
$lastc=substr($restb, -1, 1);
if ($lastc != "'" && $lastc != '"') { $lastc=""; }
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if ($ideg >= 2) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
} else {
$minstr.=substr($restb, $ideg, 1);
}
$ideg++;
}
$ideg++;
while (!(substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0'))) {
$ideg++;
}
if (substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0')) {
//echo "\n secs found\n";
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
$ideg++;
}
}
}
if ($minstr == "") { $minstr="0"; }
if ($secstr == "") { $secstr="0"; }
echo "\$minstr=" . $minstr . " and \$secstr=" . $secstr . "\n";
if ($restb == "" || $ideg == 1) {
$outct.=".0" . $outbits[$iuyt];
} else if (strpos(strtoupper($nextrestb), "W") !== false || strpos(strtoupper($nextrestb), "S") !== false) {
$minusstr="-";
//echo "\n\$Minusstr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,substr($outbits[$iuyt],0,(strlen($outbits[$iuyt]) - strlen($degstrtwo))) . $minusstr . $degstrtwo);
} else {
//echo "\n\$MinusStr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,$outbits[$iuyt]);
}

$ideg=-1;
$degstrtwo="";
//$minusstr="";
if (sizeof($outbits) > (1 + $iuyt)) {
while (substr($outbits[1 + $iuyt], $ideg, 1) <= '9' && substr($outbits[1 + $iuyt], $ideg, 1) >= '0') {
//echo "Substr(\$outbits[1 + \$iuyt], \$ideg, 1)=" . substr($outbits[1 + $iuyt], $ideg, 1) . "\n";
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1 + $iuyt], $ideg, 1) . $spares;
$ideg--;
}
}

}


}


return $hdrline . $outct;
}

?>

… reflected in a modified “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run via DMS geographicals link.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

It’s been about a three day bugbear for us that ever since we introduced the possibility for geographical (ie. latitude, longitude) co-ordinate input data to do with yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial‘s Survey Traverse web application that we encouraged a default …

  • data (field or column) order of Latitude then Longitude for geographicals … yet …
  • data order is Easting then Northing for other co-ordinates (ie. grid co-ordinates)

… and yet, in “Survey Traverse land” this does a disservice to the bearings because comparing apples with apples …

  • Latitude corresponds almost totally with Northing
  • Longitude corresponds almost totally with Easting

… that almost, above, being reflective of the fact that large distance survey legs (most likely with geographical co-ordinate data input) involve significant curvature of the Earth, which is not catered for by terrestrial (as distinct from “geodetic”) Survey Traverse calculations usually involving smaller distances (as if on a flat grid/table).

And so, where the data input is coming from a CSV file the fairly self explanatory PHP …

<?php

// Start of global initializations

$reverseorder=false;
$reversesuffix="";

// End of global initializations
// Local function initializations

$foundwordlatitude=false;
$foundwordlongitude=false;
$under180=array(true, true);
$under90=array(true, true);

// Processing logic goes here
// End of processing

if (!$under180[0] || !$under180[1]) {
$reverseorder=$reverseorder;
} else if ($under90[0] && $under90[1]) {
if (!$foundwordlongitude) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else {
$reversesuffix="<br><br><br><br>";
}
} else if ($under90[0] && $under180[1]) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else if ($under180[0] && $under90[1]) {
$reverseorder=false;
$reversesuffix="<br><br><br><br>";
}

?>

… says …

  1. if either of numerical data columns 1 and 2 has a value greater than 180 the data is in “grid co-ordinates”, not “geographicals” … else …
  2. if numerical data columns 1 and 2 all have values less than or equal to 90 will, unless in header records “Latitude” precedes “Longitude”, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  3. if numerical data column 2 all has values less than or equal to 180 and if numerical data column 1 all has values less than or equal to 90, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  4. leave the geographical input data column order in that order so that column 2 is thought of as Longitude mapped to Easting and column 1 is thought of as Latitude mapped to Northing

A retweaked “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run link showing an example of logic step 2 above … as below …

egg111.csv

We afforded backward compatibility to our blog posting links below by adding header records and/or ([EmojiCodePointList]) to our CSVs …

Type
CSV
Link
Grid co-ordinates
no places
eg.csv
327500,672500
316500,662500
322500,677500
316500,672500
314500,674500
323500,670500
321500,674500
328500,670500
eg.csv
Grid co-ordinates
with places and one emoji
egp.csv
327500,672500,”Arthur’s Seat, (Fort)”
316500,662500,”Bavelaw Castle”
322500,677500,”Caroline Park”
316500,672500,”Castle Gogar”
314500,674500,”Cat Stane”
323500,670500,”Craig Ho (onetwosevenninefiveeightdotsixfivezerothreenine)
321500,674500,”Craigcrook Castle”
328500,670500,”Craigmillar Castle”
egp.csv
Geographical co-ordinates
with places (small distances)
egg.csv
Latitude,Longitude,Placename
32.7500,67.2500,”Arthur’s Seat, (Fort)”
31.6500,66.2500,”Bavelaw Castle”
32.2500,67.7500,”Caroline Park”
31.6500,67.2500,”Castle Gogar”
31.4500,67.4500,”Cat Stane”
32.3500,67.0500,”Craig Ho”
32.1500,67.4500,”Craigcrook Castle”
32.8500,67.0500,”Craigmillar Castle”
egg.csv (and egg0.csv reverses the column header record to Longitude,Latitude,Placename so that Map Chart pattern of places more resembles shape of the grid co-ordinate canvas looks and context)
Geographical co-ordinates
with places (large distances)
egg1.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Craig Ho”
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg1.csv
Geographical co-ordinates
with places (large distances, one emoji)
egg11.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg11.csv
Geographical co-ordinates
with places (large distances, one emoji)
today’s reversed step 2 example
egg111.csv
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg111.csv


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

Onto yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial‘s contextual themes we extend those ideas by linking …

… allowing a ([EmojiCodePointList]) delimited suffix to placenames literally “spelling out” the CodePoint necessary to define the emoji, an example [EmojiCodePointList] (for Surfers Paradise) being …


Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)

… ie. 🏖️ is &#127958;&#65039;

Recognizing such a ([EmojiCodePointList]) it is stripped from the web application’s understanding of what that placename is, after having made the Emoji definition changes, as defined by the user.

A further retweaked geo_chart.php Geo Chart interfacer (as called by unchanged “last changed” SurveyTraverse.htm) Geo Chart calling live run link with an improved Emoji context, is, again, worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

We thought to improve on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial conjoining of …

… it’s good to be able to use …

  • Emojis
  • Link Lines

… but the Link Lines, then, had limited “context”. But what if the Survey Traverse had a …

  • xx-large start point Emoji
  • x-large end point Emoji

? Yes, as you can read at this useful link the CSS for font-size has some useful and interesting settings we’d like to link into our Google Chart Geo Chart SVG text newly added “class”, as required …


function emojimaybe(jnentity, jnentwo, endtag) {
var jjj;
var xclass='';
var allnum=true, iu;
var inentity=jnentity;
var inentwo=jnentwo;
var classesare=['border','bcoly','cglow','glow','xxsmall','xsmall','xx-small','x-small','smaller','small','xxlarge','xlarge','xx-large','x-large','larger','large','tenp','twentyp','onefiftyp','fiftyp','twohundredp','threehundredp','fourhundredp','fivehundredp','sixhundredp'];

if (inentwo != '') {
if (inentwo.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentwo=inentwo.replace(inentwo.replace(/\_/g,' ').split(' ')[0], inentwo.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('Xclass=' + xclass);
for (iu=0; iu<inentwo.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentwo.indexOf('_') != -1) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
allnum=true;
xclass='';
if (inentity != '') {
if (inentity.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentity=inentity.replace(inentity.replace(/\_/g,' ').split(' ')[0], inentity.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('xclass=' + xclass);
for (iu=0; iu<inentity.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentity.indexOf('_') != -1) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
return endtag;
}

A retweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link with an improved context, is worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

The recent HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial had us catering for decimal latitude and longitude input data. Within the logic for this we could be using …

… the latter choice made when the distances involved in the Survey Traverse are large. That Geo Chart is both capable of being worked to show …

  • Emojis
  • Link Lines

… an offer too good to refuse, and you can read about at Google Geo Chart Co-ordinate Emojis Tutorial. Except, that is, if in the meantime, our inhouse Geo Chart interfacing PHP logic does not keep up with Google changes to the Geo Chart itself. And that sad scenario was our discovery then, and today we fix it up.

With any data scraping feeling third-party feeling logic that we need to do here, it is “the data” that is everything, and you’re first troubleshooting question should be …

Some thing that used to work no longer works. What has changed with the underlying data?

Our strategy here was to capture the outerHTML (ie. element contents) of geo_chart.php’s “chart_div” (div) element of a scenario that should involve emojis and/or link lines for a …

  • now scenario (which is easy via a Web Inspector -> Console -> point at “chart_div” -> two finger gesture Copy OuterHTML) … versus …
  • then scenario (which we scraped together scouring snippets of data from the past existing on this MacBook Pro) of a similar scenario

… and a few prudent carriage returns revealed to us the issue. We had assumed a first HTML defs element with ID “defs” but that was no longer the case, that change cutting off a whole lot of (PHP written out) Javascript logic making Emojis and Link Lines work with Geo Charts (given savvy user usage).

A tweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link, the work leading to this more obvious after viewing today’s animated GIF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

You might say the progress made in yesterday’s HTML and Javascript and CSS Survey Traverse CSV Co-ordinates Tutorial was …

  • inordinately complex … for …
  • not enough “gain”

… two criticisms we can live with, and today, we “eat into” the credibility of, on two fronts …

  1. we extend functionality, to include “placename” data … and …

  2. that very complexity is not all bad news, as the involvement of PHP and HTML data format is also “an opportunity” to arrange data (and delimitation) to our own programming arrangements

It is “an opportunity” to come out of the PHP with two numeric fields and up to one (ie. optional placename) string field for each <br> delimited HTML record (that <br> allowing for a one Javascript codeline achieving this (though this aspect is not new to today’s work)).

It is “an opportunity” to not involve string delimitation coming out of the PHP on its way to the parent HTML iframe via its “srcdoc” attribute. How can we arrange this? Well, helped out by the usefulness of this great link we constructed the PHP function …

<?php

function clean_csv_commas($csv, $indelimis) { // thanks to https://stackoverflow.com/questions/10739016/how-to-remove-commas-between-double-quotes-in-php
$until=true;
$qdelim = '"';
$bqdelim = "'";
$altbqdelim = "&apos;";
$comma = ',';
$altcomma = '&comma;';
$altqdelim = '&quot;';
$prevcomma=FALSE;
$aftcomma=FALSE;
if ($indelimis == "'") {
$qdelim=$indelimis;
$bqdelim='"';
$altqdelim = '&apos;';
$altbqdelim = '&quot;';
}
$len = strlen($csv);
$inside_block = FALSE;
$out='';
$rep='';
for ($i=0; $i<$len; $i++) {
if (ord($csv[$i]) < 32) {
$inside_block=FALSE;
$until=false;
} else if ($csv[$i] == $qdelim) {
if ($i == 0) {
$prevcomma=FALSE;
$inside_block=TRUE;
} else if (($i + 1) == $len) {
$aftcomma=FALSE;
$inside_block=FALSE;
} else {
if ($csv[-1 + $i] == ',' || ord($csv[-1 + $i]) < 32) { $prevcomma=TRUE; } else { $prevcomma=FALSE; }
if ($csv[1 + $i] == ',' || ord($csv[1 + $i]) < 32) { $aftcomma=TRUE; } else { $aftcomma=FALSE; }
if ($inside_block) {
if ($aftcomma) { $inside_block=FALSE; }
} else {
if ($prevcomma) { $inside_block=TRUE; }
}
}
}

//if ($until) {
// $rep.="\n" . $csv[$i] . " \$inside_block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
//}
if ($csv[$i] == $comma && $inside_block) {
if ($until) {
$rep.="\n" . $csv[$i] . " \$inside-block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
}
$out.=$altcomma;
} else if ($csv[$i] == $qdelim && $inside_block && !$aftcomma && !$prevcomma) {
$out.=$altqdelim;
} else if ($csv[$i] == $bqdelim && $inside_block) {
$out.=$altbqdelim;
} else {
$out.=$csv[$i];
}

}
if ($indelimis == "") {
//file_put_contents("zerocsv.xxx", $csv);
//file_put_contents("one_csv.xxx", $rep);
//file_put_contents("onecsv.xxx", $out);
$out=str_replace("'","",str_replace('"','',clean_csv_commas($out, "'")));
//file_put_contents("twocsv.xxx", $out);
}
return $out;
}

?>

… called in this way

<?php

if (isset($_GET['csvfile'])) {
$fname=str_replace("+"," ",urldecode($_GET['csvfile']));
$csvcont='';
if (strpos(strtolower($fname),"http") !== false) {
$csvcont=file_get_contents($fname);
} else if (file_exists($fname)) {
$csvcont=file_get_contents($fname);
}
//file_put_contents("threecsv.xxx", '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>');
echo '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>';
exit;
}

?>

… to replace any need for string delimitation (via ‘ or ” characters encasing any commas mapped to &comma; or fellow string delimiters to &quot; or &apos; respectively) with HTML Entity use …


var eoff=0.0;
var noff=0.0;
var envials=[];
var pvials=[];
if (window.localStorage) {
// 34,56,78,45 ... ,
// 34,56,"One",78,45,"Two" ... ,"
// "One",34,56,"Two",78,45 ... ",
var acontt=decodeURIComponent(('' + localStorage.getItem('en_st')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (acontt != '') { localStorage.removeItem('en_st'); }
//alert(acontt);
var minicom=[];
var endelim=',';
if (acontt.indexOf(',"') != -1 && acontt.indexOf('",') != -1) {
if (eval('' + acontt.indexOf('",')) < eval('' + acontt.indexOf(',"'))) {
endelim='",';
} else {
endelim=',"';
}
} else if (acontt.indexOf(',"') != -1) {
endelim=',"';
} else if (acontt.indexOf('",') != -1) {
endelim='",';
}
var pfirst=true;
var pyoullneverfindthis='';
var jxv=0;
var xenvials=acontt.split(endelim);
xenvials.push('');
for (var ixv=0; ixv<xenvials.length; ixv++) {
if (xenvials[ixv] != '') {
if (endelim == ',"') {
pvials.push(xenvials[eval(1 + ixv)].split('"')[0]);
if (xenvials[ixv].indexOf('",') != -1) { xenvials[ixv]=xenvials[ixv].replace(xenvials[ixv].split('",')[0] + '",',''); }
minicom=xenvials[ixv].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (endelim == '",') {
pvials.push(xenvials[ixv].split('"')[0]);
if (xenvials[eval(1 + ixv)].indexOf(',"') != -1) { xenvials[eval(1 + ixv)]=xenvials[eval(1 + ixv)].replace(',"' + xenvials[eval(1 + ixv)].split(',"')[0],''); }
minicom=xenvials[eval(1 + ixv)].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (('' + xenvials[ixv]).trim() != '' && ('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '') {
//alert('envials.push(' + xenvials[ixv] + ');');
envials.push(xenvials[ixv]);
} else if (('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != pyoullneverfindthis) {
//alert('pvials.push(' + xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"') + ')');
pvials.push(xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"'));
if (pfirst) {
pfirst=false;
pyoullneverfindthis='youllnever_find_this';
}
} else {
//alert('envials.push(' + xenvials[ixv] + ')');
envials.push(xenvials[ixv]);
}
pfirst=false;
}
}
}

… as exemplified by …

Originally 327500,672500,”Arthur’s Seat, (Fort)”
Out of the PHP <html><body onload=”parent.document.getElementById(‘ifcsv’).srcdoc = ‘<pre>327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)<br></pre>';”></body></html>
Via Parent Iframe body innerHTML 327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)
window.localStorage 327500,672500,Arthur’s Seat&comma; (Fort)
Finally
E N Placename
327500 672500 Arthur’s Seat, (Fort)

And we’d like to thank this great link for today’s tutorial’s testing CSV data as per egp.csv


327500,672500,"Arthur's Seat, (Fort)"
316500,662500,"Bavelaw Castle"
322500,677500,"Caroline Park"
316500,672500,"Castle Gogar"
314500,674500,"Cat Stane"
323500,670500,"Craig Ho"
321500,674500,"Craigcrook Castle"
328500,670500,"Craigmillar Castle"

… in our changed “sister” PHP SurveyTraverse.php code called by our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS Survey Traverse Canvas Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

Onto yesterday’s HTML and Javascript and CSS NSW State Survey Traverse Tutorial progress with our Survey Traverse web application functionality we wanted to augment …

  • the existent tabular data … with …
  • new canvas graphics to show the (Easting,Northing) co-ordinate sets of the Survey Traverse

… involving the collection of minimums and maximums Javascript “ifzeromakezero” function code changes …


var edone=false, ndone=false;
var maxe=-1.0, mine=-1.0, maxn=-1.0, minn=-1.0;


function ifzeromakezero(innum,e_or_n) {
var cinnum = innum.toString();
if (cinnum.indexOf("e-") != (0 - 1)) {
if (e_or_n == 1) {
if (!edone) {
mine=0.0;
maxe=0.0;
} else {
if (mine > 0.0) { mine=0.0; }
if (maxe < 0.0) { maxe=0.0; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=0.0; maxn=0.0; } else { if (minn > 0.0) { minn=0.0; }
if (maxn < 0.0) { maxn=0.0; } } ndone=true; }

return 0.000;
}
if (e_or_n == 1) {
if (!edone) {
mine=innum;
maxe=innum;
} else {
if (mine > innum) { mine=innum; }
if (maxe < innum) { maxe=innum; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=innum; maxn=innum; } else { if (minn > innum) { minn=innum; }
if (maxn < innum) { maxn=innum; } } ndone=true; }

return innum;
}

… and the canvas creation and line plotting, featuring (thanks to (linear gradients on canvas) ideas from this excellent link) canvas Javascript code …


document.getElementById('overlays').innerHTML+='<br><br><canvas style="background-color:#f0f0f0;border:2px dashed red;" height=' + eval(40 + eval('' + maxn) - eval('' + minn)) + ' width=' + eval(40 + eval('' + maxe) - eval('' + mine)) + ' id=mycanvas></canvas>';
setTimeout(postspanscheck, 5000);
var ele=document.getElementById('mycanvas');
var context=document.getElementById('mycanvas').getContext('2d');
var iz=0, mto=true, grad;

// var pts = [[0, 0, "red"], [0, 0, "green"], [0, 0, "blue"], [0, 0, "purple"], [0, 0, "olive"], [0, 0, "magenta"], [0, 0, "cyan"], [0, 0, "brown"], [0, 0, "black"], [0, 0, "pink"], [0, 0, "darkgreen"], [0, 0, "darkblue"], [0, 0, "darkorange"]];
var pts = [[0, 0, "red"], [0, 0, "orange"], [0, 0, "yellow"], [0, 0, "green"], [0, 0, "cyan"], [0, 0, "blue"], [0, 0, "violet"]];
var begin = pts[0];
var end = pts[1];

while (document.getElementById('E' + iz)) {
if (document.getElementById('E' + iz).value != '') {
if (mto) {
context.lineWidth = 6;
context.lineJoin = "round";
context.lineCap = "round";
//context.strokeStyle = "black";
context.beginPath();
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
} else {
end=pts[eval(1 + eval(iz % 5))];
end[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
end[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
grad = context.createLinearGradient(begin[0], begin[1], end[0], end[1]);
grad.addColorStop(0, begin[2]);
grad.addColorStop(1, end[2]);
context.strokeStyle = grad;
context.lineTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
context.stroke();
//context.strokeStyle = "black";
context.beginPath();
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
}
mto=false;
}
iz++;
}
}

… via our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS NSW State Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS NSW State Survey Traverse Co-ordinates Tutorial

HTML and Javascript and CSS NSW State Survey Traverse Tutorial

Yesterday’s HTML and Javascript and CSS Survey Traverse Co-ordinates Tutorial was kind of “mathematical” by nature. Today we add some realism.

This realism stems from the discovery of a NSW State Survey mark in the local area (to the right of today’s tutorial picture). Having a Land Surveying background, an indestructible looking survey mark is a joy to behold. The thing is though, when I was doing a Bachelor Of Surveying in the late 1970’s and early 1980’s, this survey mark was much more an object of awe than perhaps such a mark is to people, even me, today. Mystery surrounded it, it taking a visit to a government agency (NSW Titles Office), and no doubt some paperwork to match, would be required to find out anything about it, Land Surveyors at the very least curious about …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (in whatever ellipsoid of relevance)
  • Reduced Level (at whatever datum of relevance)

We decided on our iPhone to feed that SS46391 survey mark name into Google, thanks, and see what comes up, and discovered the “NSW Survey Marks” iOS app that we downloaded and spent a happy half hour “in a wooooorrrrrllllllddd of discovery and interest” (well, you had to be there).

You see, this app is just great! The information above is augmented by location Sketch Maps (that a Land Surveyor from the past would have created in the NSW Titles Office).

This way, in that half hour we looked for 3 survey marks in that local area, and gleaned their co-ordinates to come up with the …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (from the NSW Survey Marks app)
  • Bearings and Distances and theodolite Angles derived

… also shown in today’s tutorial picture … via our changed SurveyTraverse.html live run link, the changes concerning allowing both …

  • decimal degrees … as well as …
  • degrees, minutes and seconds (useful for setting an angle with a theodolite)

… for those aforesaid mentioned Angles and Bearings (with your compass or iPhone compass app).

Some of this “NSW Survey Marks” app’s workings can be viewed with today’s accompanying PDF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

Here is a tutorial showing some client-side basics in HTML and Javascript and CSS all in the one HTML file, to simplify concepts. The tutorial subject matter is a webpage to perform Survey Traverse calculations. A Survey Traverse is:

Traverse is a method in the field of surveying to establish control networks.[1] It is also used in geodesy. Traverse networks involve placing survey stations along a line or path of travel, and then using the previously surveyed points as a base for observing the next point. Traverse networks have many advantages, including:

Less reconnaissance and organization needed;
While in other systems, which may require the survey to be performed along a rigid polygon shape, the traverse can change to any shape and thus can accommodate a great deal of different terrains;
Only a few observations need to be taken at each station, whereas in other survey networks a great deal of angular and linear observations need to be made and considered;
Traverse networks are free of the strength of figure considerations that happen in triangular systems;
Scale error does not add up as the traverse is performed. Azimuth swing errors can also be reduced by increasing the distance between stations.

The traverse is more accurate than triangulateration[2] (a combined function of the triangulation and trilateration practice).[3]

Let’s see some simple HTML in action in a tutorial …

Link to HTML “spiritual home” … at W3Schools has many tutorials.
Link to Survey Traverse live run … here.
Link to Survey Traverse live run (additional Google Line Chart functionality) here.
Link to Survey Traverse information … from Wikipedia from which quote above comes.
Link to some downloadable HTML code … rename to SurveyTraverse.html which packages up a lot of Javascript and a little bit of CSS … or JaCvasScriptS … not sure whether this would ever catch on.
Link to some downloadable PHP programming code (additional Google Line Chart functionality) … rename to SurveyTraverse.php

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

HTML and Javascript and CSS Survey Traverse Interactive Input Tutorial

HTML and Javascript and CSS Survey Traverse Interactive Input Tutorial

HTML and Javascript and CSS Survey Traverse Interactive Input Tutorial

There is a vast difference to the complexity of web applications that …

  • just impart information (in a broadcasting style) … versus ones that …
  • accept interactive user input as a variable to then impart information that differs depending on those user entries

… and pretty obviously the latter one above presents many more challenges than the former. Yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial (and today’s) web application is an example where there is a great deal of interactive user entry offered.

You will find coding and deploying such web applications there are categories of users, from those who try to avail themselves of all the “bells and whistles” available right through to those who just get their kicks trying to make it fail. A common interactive entry feature that benefits from a bit of planning is your HTML input type=text textbox. Do you think of emojis as text? Well, they are, and often we don’t cater for emoji data entered into textboxes unless there is considerable “follow through” on the web application. Today’s web application has us using a five iron on a par four.

We have two scenarios we can think of that catering for interactively entered emoji characters (on macOS, using the control-command-space key sequence) …

  • in first Javascript prompt window (as a chance for user to define a default Geo Chart emoji (which can be none))
  • in Placename textbox (anywhere) as a specific Emoji definition for a particular Survey Traverse station (or point)

So what is the mechanism to share these new settings between calls of the web application? We’ve decided to use hashtag # navigation, because we are only dealing with top level (client) HTML/Javascript/CSS with this web application (rather than serverside PHP). Did you know you can string along hashtag concepts as per …


#DefaultEmojiCodePoint#GeoChartWidth#GeoChartHeight

… those interim # above still appearing within …


location.hash

… and so being quite a useful alternative “settings imparting tool” but not as good as (the “GET”) ? and & arguments, because caching does not recognize a changed location.hash as it does a changed document.URL (URL).

Our changed SurveyTraverse.htm Geo Chart (1000 x 630) calling live run via DMS geographicals with no Emojis link is worth mulling over.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial

Supposing you’re a crow setting out on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial‘s …

  • Australian Capital Cities trip …
  • stopping off at each city to take a break … and …
  • you want to know which direction to head … and …
  • how far away is the next city

… well, we’re here to help, thanks to the advice at this very useful link to calculate …

  • First Azimuth (ie. first bearing you head off with, noting that this bearing changes as the trip goes on) …

    function doazimuthgcd() { // thanks to https://www.movable-type.co.uk/scripts/latlong.html
    // dE0 (has E0 longitude and N0 latitude),dE1 etc dN0,dN1 etc
    // Formula: θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
    // where φ1,λ1 is the start point, φ2,λ2 the end point (Δλ is the difference in longitude)
    var kjw=0, kkjw=1;
    var thisaz=0.0, deltalong;
    var sparec=document.getElementById('tde').innerHTML;
    if (document.getElementById('tde').innerHTML.indexOf('ongitude') != -1 && document.getElementById('tde').innerHTML.indexOf(' (') != -1) {
    document.getElementById('tde').innerHTML=sparec.replace(' (',' (<font color=blue>').replace(')',')</font>');
    sparec=document.getElementById('tdn').innerHTML;
    document.getElementById('tdn').innerHTML=sparec.replace(' (',' (<font color=blue>').replace(')',')</font>');
    sparec=document.getElementById('diffe').innerHTML;
    document.getElementById('diffe').innerHTML='<font color=blue>First Azimuth / </font>' + sparec;
    sparec=document.getElementById('diffn').innerHTML;
    document.getElementById('diffn').innerHTML='<font color=blue>Great Circle Distance / </font>' + sparec;
    while (document.getElementById('dE' + kjw)) {
    deltalong=eval(eval(eval('' + document.getElementById('E' + kkjw).value) - eval('' + document.getElementById('E' + kjw).value)) * eval(Math.PI / 180.0));
    // Formula: θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
    thisaz=
    eval('' +
    Math.atan2(
    eval(
    Math.sin(deltalong) *
    Math.cos(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0)))
    ),
    eval(
    eval(
    Math.cos(eval(eval('' + document.getElementById('N' + kjw).value) * eval(Math.PI / 180.0))) *
    Math.sin(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0)))) -
    eval(
    Math.sin(eval(eval('' + document.getElementById('N' + kjw).value) * eval(Math.PI / 180.0))) *
    Math.cos(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0))) *
    Math.cos(deltalong))
    )
    )) * eval(180.0 / Math.PI);
    if (thisaz < 0.0) { thisaz+=360.0; }
    document.getElementById('dE' + kjw).className='fatd';
    document.getElementById('dE' + kjw).innerHTML='' + thisaz + '';
    document.getElementById('dE' + kjw).title=dechange(document.getElementById('dE' + kjw).innerHTML, kjw, numlegs);
    document.getElementById('dN' + kjw).innerHTML='<font color=blue>' + great_circle_distance(eval('' + document.getElementById('E' + kjw).value), eval('' + document.getElementById('N' + kjw).value), eval('' + document.getElementById('E' + kkjw).value), eval('' + document.getElementById('N' + kkjw).value)) + '</font>';
    kjw++;
    kkjw++;
    }
    //document.title+=' ... ' + kjw;
    }
    }
  • Great Circle Distance …

    function great_circle_distance(talis, gnolis, latis, longis) {
    var ourdist=0.0;
    var rgnol=eval((gnolis) * Math.PI / 180.0);
    var rtal=eval((talis) * Math.PI / 180.0);
    var rlong=eval((longis) * Math.PI / 180.0);
    var rlat=eval((latis) * Math.PI / 180.0);
    var deltalong = Math.abs(eval(((gnolis)-(longis)) * Math.PI / 180.0));
    var acof = eval(Math.sin(rtal) * Math.sin(rlat)) + (Math.cos(rtal) * Math.cos(rlat) * Math.cos(deltalong)); // via //en.wikipedia.org/wiki/Great-circle_distance ... thanks
    //ourdist = eval(Math.round((Math.acos(acof) * 6371000.0) + 0.00001) * 100) / 100;
    ourdist = eval((Math.acos(acof) * 6371000.0) + 0.00001);
    return ourdist;
    }

… that now gets incorporated into our changed SurveyTraverse.htm Geo Chart calling live run via DMS geographicals link.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

Up to and including yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial‘s web application’s CSV co-ordinate formats supported included …

  • grid Easting and Northing co-ordinates
  • geographical Latitude and LongitudeLongitude and Latitude decimal co-ordinates … and today we add onto that list …
  • geographical Latitude and LongitudeLongitude and Latitude DMS (degrees, minutes, seconds) co-ordinates

… that latter format popular with Wikipedia‘s geodata content, and many other sources too. We took some such Wikipedia content for Australia’s capital cities and fed it into a Sydney.csv

“31°57′8″S”,”115°51′32″E”,”Perth”
“34°55′44″S”,”138°36′4″E”,”Adelaide”
“12°26′17″S”,”130°50′28″E”,”Darwin”
“27°28′04″S”,”153°01′41″E”,”Brisbane”
“33°51′54″S”,”151°12′34″E”,”Sydney”
“35°17′35″S”,”149°07′37″E”,”Canberra”
“37°48′49″S”,”144°57′47″E”,”Melbourne”
“42°52′50″S”,”147°19′30″E”,”Hobart”

… and onto an execution using such DMS geographicals above …

… possible because of a new PHP function …

<?php

function dmscheck($inct) {

// "33°51′54″S","151°12′34″E","Sydney"
// "34°55′44″S","138°36′4″E","Adelaide"
$lathfound=false;
$longhfound=false;
$restb="";
$degstrone="";
$reststrone="";
$degstrtwo="";
$reststrtwo="";
$minstr="";
$isdms=false;
$secstr="";
$nextrestb="";
$minusstr="";
$hdrline="";
$spares="";
$ideg=-1;
$lastc="";
$outct=$inct;
$outbits=explode("°", $inct);
if (strpos(strtolower($outbits[0]), "latitude") !== false && strpos(strtolower($outbits[0]), "longitude") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "latitude") < strpos(strtolower($outbits[0]), "longitude")) {
$lathfound=true;
} else {
$longhfound=true;
}
} else if (strpos(strtolower($outbits[0]), "lat") !== false && strpos(strtolower($outbits[0]), "long") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "lat") < strpos(strtolower($outbits[0]), "long")) {
$lathfound=true;
} else {
$longhfound=true;
}
}


if (sizeof($outbits) <= 2 && $isdms) {
$outct=str_replace(".0", "°0", str_replace(".1", "°1", str_replace(".2", "°2", str_replace(".3", "°3", str_replace(".4", "°4", str_replace(".5", "°5", str_replace(".6", "°6", str_replace(".7", "°7", str_replace(".8", "°8", str_replace(".9", "°9", $inct))))))))));
$outbits=explode("°", $outct);
$outct=$inct;
}


if (sizeof($outbits) > 2) {


$reststrone=strtoupper(explode(",", $outbits[1])[0]);
$minusstr="";
if (strpos(strtoupper($reststrone), "W") !== false || strpos(strtoupper($reststrone), "S") !== false) {
$minusstr="-";
}
//echo "\n \$reststrone=" . $reststrone . " \$minusstr=" . $minusstr . "\n";
//$reststrtwo=strtoupper(explode(",", $outbits[1])[0]);
if (!$lathfound && !$longhfound) {
while (substr($outbits[0], $ideg, 1) <= '9' && substr($outbits[0], $ideg, 1) >= '0') {
//echo "substr(\$outbits[0], \$ideg, 1)=" . substr($outbits[0], $ideg, 1) . "\n";
$spares=$degstrone;
$degstrone=substr($outbits[0], $ideg, 1) . $spares;
$ideg--;
}
$ideg=-1;
while (substr($outbits[1], $ideg, 1) <= '9' && substr($outbits[1], $ideg, 1) >= '0') {
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1], $ideg, 1) . $spares;
$ideg--;
}
if (strpos($reststrone, "N") !== false || strpos($reststrone, "S") !== false) {
if ($degstrone <= 90.0) {
$hdrline="Latitude,Longitude,\n";
}
}
}


$outct=substr($outbits[0],0,(strlen($outbits[0]) - strlen($degstrone))) . $minusstr . $degstrone;
for ($iuyt=1; $iuyt<sizeof($outbits); $iuyt++) {

$minusstr="";
$restb=explode(",", $outbits[$iuyt])[0];
$nextrestb="";
if (sizeof($outbits) > (1 + $iuyt)) {
$nextrestb=explode(",", $outbits[1 + $iuyt])[0];
}
//echo "\n\$restb=" . $restb . "\n<br>";
$minstr="";
$secstr="";
$ideg=0;
if (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
$lastc=substr($restb, -1, 1);
if ($lastc != "'" && $lastc != '"') { $lastc=""; }
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if ($ideg >= 2) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
} else {
$minstr.=substr($restb, $ideg, 1);
}
$ideg++;
}
$ideg++;
while (!(substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0'))) {
$ideg++;
}
if (substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0')) {
//echo "\n secs found\n";
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
$ideg++;
}
}
}
if ($minstr == "") { $minstr="0"; }
if ($secstr == "") { $secstr="0"; }
echo "\$minstr=" . $minstr . " and \$secstr=" . $secstr . "\n";
if ($restb == "" || $ideg == 1) {
$outct.=".0" . $outbits[$iuyt];
} else if (strpos(strtoupper($nextrestb), "W") !== false || strpos(strtoupper($nextrestb), "S") !== false) {
$minusstr="-";
//echo "\n\$Minusstr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,substr($outbits[$iuyt],0,(strlen($outbits[$iuyt]) - strlen($degstrtwo))) . $minusstr . $degstrtwo);
} else {
//echo "\n\$MinusStr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,$outbits[$iuyt]);
}

$ideg=-1;
$degstrtwo="";
//$minusstr="";
if (sizeof($outbits) > (1 + $iuyt)) {
while (substr($outbits[1 + $iuyt], $ideg, 1) <= '9' && substr($outbits[1 + $iuyt], $ideg, 1) >= '0') {
//echo "Substr(\$outbits[1 + \$iuyt], \$ideg, 1)=" . substr($outbits[1 + $iuyt], $ideg, 1) . "\n";
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1 + $iuyt], $ideg, 1) . $spares;
$ideg--;
}
}

}


}


return $hdrline . $outct;
}

?>

… reflected in a modified “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run via DMS geographicals link.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

It’s been about a three day bugbear for us that ever since we introduced the possibility for geographical (ie. latitude, longitude) co-ordinate input data to do with yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial‘s Survey Traverse web application that we encouraged a default …

  • data (field or column) order of Latitude then Longitude for geographicals … yet …
  • data order is Easting then Northing for other co-ordinates (ie. grid co-ordinates)

… and yet, in “Survey Traverse land” this does a disservice to the bearings because comparing apples with apples …

  • Latitude corresponds almost totally with Northing
  • Longitude corresponds almost totally with Easting

… that almost, above, being reflective of the fact that large distance survey legs (most likely with geographical co-ordinate data input) involve significant curvature of the Earth, which is not catered for by terrestrial (as distinct from “geodetic”) Survey Traverse calculations usually involving smaller distances (as if on a flat grid/table).

And so, where the data input is coming from a CSV file the fairly self explanatory PHP …

<?php

// Start of global initializations

$reverseorder=false;
$reversesuffix="";

// End of global initializations
// Local function initializations

$foundwordlatitude=false;
$foundwordlongitude=false;
$under180=array(true, true);
$under90=array(true, true);

// Processing logic goes here
// End of processing

if (!$under180[0] || !$under180[1]) {
$reverseorder=$reverseorder;
} else if ($under90[0] && $under90[1]) {
if (!$foundwordlongitude) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else {
$reversesuffix="<br><br><br><br>";
}
} else if ($under90[0] && $under180[1]) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else if ($under180[0] && $under90[1]) {
$reverseorder=false;
$reversesuffix="<br><br><br><br>";
}

?>

… says …

  1. if either of numerical data columns 1 and 2 has a value greater than 180 the data is in “grid co-ordinates”, not “geographicals” … else …
  2. if numerical data columns 1 and 2 all have values less than or equal to 90 will, unless in header records “Latitude” precedes “Longitude”, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  3. if numerical data column 2 all has values less than or equal to 180 and if numerical data column 1 all has values less than or equal to 90, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  4. leave the geographical input data column order in that order so that column 2 is thought of as Longitude mapped to Easting and column 1 is thought of as Latitude mapped to Northing

A retweaked “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run link showing an example of logic step 2 above … as below …

egg111.csv

We afforded backward compatibility to our blog posting links below by adding header records and/or ([EmojiCodePointList]) to our CSVs …

Type
CSV
Link
Grid co-ordinates
no places
eg.csv
327500,672500
316500,662500
322500,677500
316500,672500
314500,674500
323500,670500
321500,674500
328500,670500
eg.csv
Grid co-ordinates
with places and one emoji
egp.csv
327500,672500,”Arthur’s Seat, (Fort)”
316500,662500,”Bavelaw Castle”
322500,677500,”Caroline Park”
316500,672500,”Castle Gogar”
314500,674500,”Cat Stane”
323500,670500,”Craig Ho (onetwosevenninefiveeightdotsixfivezerothreenine)
321500,674500,”Craigcrook Castle”
328500,670500,”Craigmillar Castle”
egp.csv
Geographical co-ordinates
with places (small distances)
egg.csv
Latitude,Longitude,Placename
32.7500,67.2500,”Arthur’s Seat, (Fort)”
31.6500,66.2500,”Bavelaw Castle”
32.2500,67.7500,”Caroline Park”
31.6500,67.2500,”Castle Gogar”
31.4500,67.4500,”Cat Stane”
32.3500,67.0500,”Craig Ho”
32.1500,67.4500,”Craigcrook Castle”
32.8500,67.0500,”Craigmillar Castle”
egg.csv (and egg0.csv reverses the column header record to Longitude,Latitude,Placename so that Map Chart pattern of places more resembles shape of the grid co-ordinate canvas looks and context)
Geographical co-ordinates
with places (large distances)
egg1.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Craig Ho”
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg1.csv
Geographical co-ordinates
with places (large distances, one emoji)
egg11.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg11.csv
Geographical co-ordinates
with places (large distances, one emoji)
today’s reversed step 2 example
egg111.csv
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg111.csv


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

Onto yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial‘s contextual themes we extend those ideas by linking …

… allowing a ([EmojiCodePointList]) delimited suffix to placenames literally “spelling out” the CodePoint necessary to define the emoji, an example [EmojiCodePointList] (for Surfers Paradise) being …


Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)

… ie. 🏖️ is &#127958;&#65039;

Recognizing such a ([EmojiCodePointList]) it is stripped from the web application’s understanding of what that placename is, after having made the Emoji definition changes, as defined by the user.

A further retweaked geo_chart.php Geo Chart interfacer (as called by unchanged “last changed” SurveyTraverse.htm) Geo Chart calling live run link with an improved Emoji context, is, again, worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

We thought to improve on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial conjoining of …

… it’s good to be able to use …

  • Emojis
  • Link Lines

… but the Link Lines, then, had limited “context”. But what if the Survey Traverse had a …

  • xx-large start point Emoji
  • x-large end point Emoji

? Yes, as you can read at this useful link the CSS for font-size has some useful and interesting settings we’d like to link into our Google Chart Geo Chart SVG text newly added “class”, as required …


function emojimaybe(jnentity, jnentwo, endtag) {
var jjj;
var xclass='';
var allnum=true, iu;
var inentity=jnentity;
var inentwo=jnentwo;
var classesare=['border','bcoly','cglow','glow','xxsmall','xsmall','xx-small','x-small','smaller','small','xxlarge','xlarge','xx-large','x-large','larger','large','tenp','twentyp','onefiftyp','fiftyp','twohundredp','threehundredp','fourhundredp','fivehundredp','sixhundredp'];

if (inentwo != '') {
if (inentwo.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentwo=inentwo.replace(inentwo.replace(/\_/g,' ').split(' ')[0], inentwo.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('Xclass=' + xclass);
for (iu=0; iu<inentwo.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentwo.indexOf('_') != -1) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
allnum=true;
xclass='';
if (inentity != '') {
if (inentity.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentity=inentity.replace(inentity.replace(/\_/g,' ').split(' ')[0], inentity.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('xclass=' + xclass);
for (iu=0; iu<inentity.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentity.indexOf('_') != -1) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
return endtag;
}

A retweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link with an improved context, is worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

The recent HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial had us catering for decimal latitude and longitude input data. Within the logic for this we could be using …

… the latter choice made when the distances involved in the Survey Traverse are large. That Geo Chart is both capable of being worked to show …

  • Emojis
  • Link Lines

… an offer too good to refuse, and you can read about at Google Geo Chart Co-ordinate Emojis Tutorial. Except, that is, if in the meantime, our inhouse Geo Chart interfacing PHP logic does not keep up with Google changes to the Geo Chart itself. And that sad scenario was our discovery then, and today we fix it up.

With any data scraping feeling third-party feeling logic that we need to do here, it is “the data” that is everything, and you’re first troubleshooting question should be …

Some thing that used to work no longer works. What has changed with the underlying data?

Our strategy here was to capture the outerHTML (ie. element contents) of geo_chart.php’s “chart_div” (div) element of a scenario that should involve emojis and/or link lines for a …

  • now scenario (which is easy via a Web Inspector -> Console -> point at “chart_div” -> two finger gesture Copy OuterHTML) … versus …
  • then scenario (which we scraped together scouring snippets of data from the past existing on this MacBook Pro) of a similar scenario

… and a few prudent carriage returns revealed to us the issue. We had assumed a first HTML defs element with ID “defs” but that was no longer the case, that change cutting off a whole lot of (PHP written out) Javascript logic making Emojis and Link Lines work with Geo Charts (given savvy user usage).

A tweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link, the work leading to this more obvious after viewing today’s animated GIF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

You might say the progress made in yesterday’s HTML and Javascript and CSS Survey Traverse CSV Co-ordinates Tutorial was …

  • inordinately complex … for …
  • not enough “gain”

… two criticisms we can live with, and today, we “eat into” the credibility of, on two fronts …

  1. we extend functionality, to include “placename” data … and …

  2. that very complexity is not all bad news, as the involvement of PHP and HTML data format is also “an opportunity” to arrange data (and delimitation) to our own programming arrangements

It is “an opportunity” to come out of the PHP with two numeric fields and up to one (ie. optional placename) string field for each <br> delimited HTML record (that <br> allowing for a one Javascript codeline achieving this (though this aspect is not new to today’s work)).

It is “an opportunity” to not involve string delimitation coming out of the PHP on its way to the parent HTML iframe via its “srcdoc” attribute. How can we arrange this? Well, helped out by the usefulness of this great link we constructed the PHP function …

<?php

function clean_csv_commas($csv, $indelimis) { // thanks to https://stackoverflow.com/questions/10739016/how-to-remove-commas-between-double-quotes-in-php
$until=true;
$qdelim = '"';
$bqdelim = "'";
$altbqdelim = "&apos;";
$comma = ',';
$altcomma = '&comma;';
$altqdelim = '&quot;';
$prevcomma=FALSE;
$aftcomma=FALSE;
if ($indelimis == "'") {
$qdelim=$indelimis;
$bqdelim='"';
$altqdelim = '&apos;';
$altbqdelim = '&quot;';
}
$len = strlen($csv);
$inside_block = FALSE;
$out='';
$rep='';
for ($i=0; $i<$len; $i++) {
if (ord($csv[$i]) < 32) {
$inside_block=FALSE;
$until=false;
} else if ($csv[$i] == $qdelim) {
if ($i == 0) {
$prevcomma=FALSE;
$inside_block=TRUE;
} else if (($i + 1) == $len) {
$aftcomma=FALSE;
$inside_block=FALSE;
} else {
if ($csv[-1 + $i] == ',' || ord($csv[-1 + $i]) < 32) { $prevcomma=TRUE; } else { $prevcomma=FALSE; }
if ($csv[1 + $i] == ',' || ord($csv[1 + $i]) < 32) { $aftcomma=TRUE; } else { $aftcomma=FALSE; }
if ($inside_block) {
if ($aftcomma) { $inside_block=FALSE; }
} else {
if ($prevcomma) { $inside_block=TRUE; }
}
}
}

//if ($until) {
// $rep.="\n" . $csv[$i] . " \$inside_block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
//}
if ($csv[$i] == $comma && $inside_block) {
if ($until) {
$rep.="\n" . $csv[$i] . " \$inside-block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
}
$out.=$altcomma;
} else if ($csv[$i] == $qdelim && $inside_block && !$aftcomma && !$prevcomma) {
$out.=$altqdelim;
} else if ($csv[$i] == $bqdelim && $inside_block) {
$out.=$altbqdelim;
} else {
$out.=$csv[$i];
}

}
if ($indelimis == "") {
//file_put_contents("zerocsv.xxx", $csv);
//file_put_contents("one_csv.xxx", $rep);
//file_put_contents("onecsv.xxx", $out);
$out=str_replace("'","",str_replace('"','',clean_csv_commas($out, "'")));
//file_put_contents("twocsv.xxx", $out);
}
return $out;
}

?>

… called in this way

<?php

if (isset($_GET['csvfile'])) {
$fname=str_replace("+"," ",urldecode($_GET['csvfile']));
$csvcont='';
if (strpos(strtolower($fname),"http") !== false) {
$csvcont=file_get_contents($fname);
} else if (file_exists($fname)) {
$csvcont=file_get_contents($fname);
}
//file_put_contents("threecsv.xxx", '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>');
echo '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>';
exit;
}

?>

… to replace any need for string delimitation (via ‘ or ” characters encasing any commas mapped to &comma; or fellow string delimiters to &quot; or &apos; respectively) with HTML Entity use …


var eoff=0.0;
var noff=0.0;
var envials=[];
var pvials=[];
if (window.localStorage) {
// 34,56,78,45 ... ,
// 34,56,"One",78,45,"Two" ... ,"
// "One",34,56,"Two",78,45 ... ",
var acontt=decodeURIComponent(('' + localStorage.getItem('en_st')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (acontt != '') { localStorage.removeItem('en_st'); }
//alert(acontt);
var minicom=[];
var endelim=',';
if (acontt.indexOf(',"') != -1 && acontt.indexOf('",') != -1) {
if (eval('' + acontt.indexOf('",')) < eval('' + acontt.indexOf(',"'))) {
endelim='",';
} else {
endelim=',"';
}
} else if (acontt.indexOf(',"') != -1) {
endelim=',"';
} else if (acontt.indexOf('",') != -1) {
endelim='",';
}
var pfirst=true;
var pyoullneverfindthis='';
var jxv=0;
var xenvials=acontt.split(endelim);
xenvials.push('');
for (var ixv=0; ixv<xenvials.length; ixv++) {
if (xenvials[ixv] != '') {
if (endelim == ',"') {
pvials.push(xenvials[eval(1 + ixv)].split('"')[0]);
if (xenvials[ixv].indexOf('",') != -1) { xenvials[ixv]=xenvials[ixv].replace(xenvials[ixv].split('",')[0] + '",',''); }
minicom=xenvials[ixv].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (endelim == '",') {
pvials.push(xenvials[ixv].split('"')[0]);
if (xenvials[eval(1 + ixv)].indexOf(',"') != -1) { xenvials[eval(1 + ixv)]=xenvials[eval(1 + ixv)].replace(',"' + xenvials[eval(1 + ixv)].split(',"')[0],''); }
minicom=xenvials[eval(1 + ixv)].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (('' + xenvials[ixv]).trim() != '' && ('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '') {
//alert('envials.push(' + xenvials[ixv] + ');');
envials.push(xenvials[ixv]);
} else if (('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != pyoullneverfindthis) {
//alert('pvials.push(' + xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"') + ')');
pvials.push(xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"'));
if (pfirst) {
pfirst=false;
pyoullneverfindthis='youllnever_find_this';
}
} else {
//alert('envials.push(' + xenvials[ixv] + ')');
envials.push(xenvials[ixv]);
}
pfirst=false;
}
}
}

… as exemplified by …

Originally 327500,672500,”Arthur’s Seat, (Fort)”
Out of the PHP <html><body onload=”parent.document.getElementById(‘ifcsv’).srcdoc = ‘<pre>327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)<br></pre>';”></body></html>
Via Parent Iframe body innerHTML 327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)
window.localStorage 327500,672500,Arthur’s Seat&comma; (Fort)
Finally
E N Placename
327500 672500 Arthur’s Seat, (Fort)

And we’d like to thank this great link for today’s tutorial’s testing CSV data as per egp.csv


327500,672500,"Arthur's Seat, (Fort)"
316500,662500,"Bavelaw Castle"
322500,677500,"Caroline Park"
316500,672500,"Castle Gogar"
314500,674500,"Cat Stane"
323500,670500,"Craig Ho"
321500,674500,"Craigcrook Castle"
328500,670500,"Craigmillar Castle"

… in our changed “sister” PHP SurveyTraverse.php code called by our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS Survey Traverse Canvas Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

Onto yesterday’s HTML and Javascript and CSS NSW State Survey Traverse Tutorial progress with our Survey Traverse web application functionality we wanted to augment …

  • the existent tabular data … with …
  • new canvas graphics to show the (Easting,Northing) co-ordinate sets of the Survey Traverse

… involving the collection of minimums and maximums Javascript “ifzeromakezero” function code changes …


var edone=false, ndone=false;
var maxe=-1.0, mine=-1.0, maxn=-1.0, minn=-1.0;


function ifzeromakezero(innum,e_or_n) {
var cinnum = innum.toString();
if (cinnum.indexOf("e-") != (0 - 1)) {
if (e_or_n == 1) {
if (!edone) {
mine=0.0;
maxe=0.0;
} else {
if (mine > 0.0) { mine=0.0; }
if (maxe < 0.0) { maxe=0.0; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=0.0; maxn=0.0; } else { if (minn > 0.0) { minn=0.0; }
if (maxn < 0.0) { maxn=0.0; } } ndone=true; }

return 0.000;
}
if (e_or_n == 1) {
if (!edone) {
mine=innum;
maxe=innum;
} else {
if (mine > innum) { mine=innum; }
if (maxe < innum) { maxe=innum; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=innum; maxn=innum; } else { if (minn > innum) { minn=innum; }
if (maxn < innum) { maxn=innum; } } ndone=true; }

return innum;
}

… and the canvas creation and line plotting, featuring (thanks to (linear gradients on canvas) ideas from this excellent link) canvas Javascript code …


document.getElementById('overlays').innerHTML+='<br><br><canvas style="background-color:#f0f0f0;border:2px dashed red;" height=' + eval(40 + eval('' + maxn) - eval('' + minn)) + ' width=' + eval(40 + eval('' + maxe) - eval('' + mine)) + ' id=mycanvas></canvas>';
setTimeout(postspanscheck, 5000);
var ele=document.getElementById('mycanvas');
var context=document.getElementById('mycanvas').getContext('2d');
var iz=0, mto=true, grad;

// var pts = [[0, 0, "red"], [0, 0, "green"], [0, 0, "blue"], [0, 0, "purple"], [0, 0, "olive"], [0, 0, "magenta"], [0, 0, "cyan"], [0, 0, "brown"], [0, 0, "black"], [0, 0, "pink"], [0, 0, "darkgreen"], [0, 0, "darkblue"], [0, 0, "darkorange"]];
var pts = [[0, 0, "red"], [0, 0, "orange"], [0, 0, "yellow"], [0, 0, "green"], [0, 0, "cyan"], [0, 0, "blue"], [0, 0, "violet"]];
var begin = pts[0];
var end = pts[1];

while (document.getElementById('E' + iz)) {
if (document.getElementById('E' + iz).value != '') {
if (mto) {
context.lineWidth = 6;
context.lineJoin = "round";
context.lineCap = "round";
//context.strokeStyle = "black";
context.beginPath();
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
} else {
end=pts[eval(1 + eval(iz % 5))];
end[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
end[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
grad = context.createLinearGradient(begin[0], begin[1], end[0], end[1]);
grad.addColorStop(0, begin[2]);
grad.addColorStop(1, end[2]);
context.strokeStyle = grad;
context.lineTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
context.stroke();
//context.strokeStyle = "black";
context.beginPath();
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
}
mto=false;
}
iz++;
}
}

… via our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS NSW State Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS NSW State Survey Traverse Co-ordinates Tutorial

HTML and Javascript and CSS NSW State Survey Traverse Tutorial

Yesterday’s HTML and Javascript and CSS Survey Traverse Co-ordinates Tutorial was kind of “mathematical” by nature. Today we add some realism.

This realism stems from the discovery of a NSW State Survey mark in the local area (to the right of today’s tutorial picture). Having a Land Surveying background, an indestructible looking survey mark is a joy to behold. The thing is though, when I was doing a Bachelor Of Surveying in the late 1970’s and early 1980’s, this survey mark was much more an object of awe than perhaps such a mark is to people, even me, today. Mystery surrounded it, it taking a visit to a government agency (NSW Titles Office), and no doubt some paperwork to match, would be required to find out anything about it, Land Surveyors at the very least curious about …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (in whatever ellipsoid of relevance)
  • Reduced Level (at whatever datum of relevance)

We decided on our iPhone to feed that SS46391 survey mark name into Google, thanks, and see what comes up, and discovered the “NSW Survey Marks” iOS app that we downloaded and spent a happy half hour “in a wooooorrrrrllllllddd of discovery and interest” (well, you had to be there).

You see, this app is just great! The information above is augmented by location Sketch Maps (that a Land Surveyor from the past would have created in the NSW Titles Office).

This way, in that half hour we looked for 3 survey marks in that local area, and gleaned their co-ordinates to come up with the …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (from the NSW Survey Marks app)
  • Bearings and Distances and theodolite Angles derived

… also shown in today’s tutorial picture … via our changed SurveyTraverse.html live run link, the changes concerning allowing both …

  • decimal degrees … as well as …
  • degrees, minutes and seconds (useful for setting an angle with a theodolite)

… for those aforesaid mentioned Angles and Bearings (with your compass or iPhone compass app).

Some of this “NSW Survey Marks” app’s workings can be viewed with today’s accompanying PDF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

Here is a tutorial showing some client-side basics in HTML and Javascript and CSS all in the one HTML file, to simplify concepts. The tutorial subject matter is a webpage to perform Survey Traverse calculations. A Survey Traverse is:

Traverse is a method in the field of surveying to establish control networks.[1] It is also used in geodesy. Traverse networks involve placing survey stations along a line or path of travel, and then using the previously surveyed points as a base for observing the next point. Traverse networks have many advantages, including:

Less reconnaissance and organization needed;
While in other systems, which may require the survey to be performed along a rigid polygon shape, the traverse can change to any shape and thus can accommodate a great deal of different terrains;
Only a few observations need to be taken at each station, whereas in other survey networks a great deal of angular and linear observations need to be made and considered;
Traverse networks are free of the strength of figure considerations that happen in triangular systems;
Scale error does not add up as the traverse is performed. Azimuth swing errors can also be reduced by increasing the distance between stations.

The traverse is more accurate than triangulateration[2] (a combined function of the triangulation and trilateration practice).[3]

Let’s see some simple HTML in action in a tutorial …

Link to HTML “spiritual home” … at W3Schools has many tutorials.
Link to Survey Traverse live run … here.
Link to Survey Traverse live run (additional Google Line Chart functionality) here.
Link to Survey Traverse information … from Wikipedia from which quote above comes.
Link to some downloadable HTML code … rename to SurveyTraverse.html which packages up a lot of Javascript and a little bit of CSS … or JaCvasScriptS … not sure whether this would ever catch on.
Link to some downloadable PHP programming code (additional Google Line Chart functionality) … rename to SurveyTraverse.php

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Navigation Tutorial

Supposing you’re a crow setting out on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial‘s …

  • Australian Capital Cities trip …
  • stopping off at each city to take a break … and …
  • you want to know which direction to head … and …
  • how far away is the next city

… well, we’re here to help, thanks to the advice at this very useful link to calculate …

  • First Azimuth (ie. first bearing you head off with, noting that this bearing changes as the trip goes on) …

    function doazimuthgcd() { // thanks to https://www.movable-type.co.uk/scripts/latlong.html
    // dE0 (has E0 longitude and N0 latitude),dE1 etc dN0,dN1 etc
    // Formula: θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
    // where φ1,λ1 is the start point, φ2,λ2 the end point (Δλ is the difference in longitude)
    var kjw=0, kkjw=1;
    var thisaz=0.0, deltalong;
    var sparec=document.getElementById('tde').innerHTML;
    if (document.getElementById('tde').innerHTML.indexOf('ongitude') != -1 && document.getElementById('tde').innerHTML.indexOf(' (') != -1) {
    document.getElementById('tde').innerHTML=sparec.replace(' (',' (<font color=blue>').replace(')',')</font>');
    sparec=document.getElementById('tdn').innerHTML;
    document.getElementById('tdn').innerHTML=sparec.replace(' (',' (<font color=blue>').replace(')',')</font>');
    sparec=document.getElementById('diffe').innerHTML;
    document.getElementById('diffe').innerHTML='<font color=blue>First Azimuth / </font>' + sparec;
    sparec=document.getElementById('diffn').innerHTML;
    document.getElementById('diffn').innerHTML='<font color=blue>Great Circle Distance / </font>' + sparec;
    while (document.getElementById('dE' + kjw)) {
    deltalong=eval(eval(eval('' + document.getElementById('E' + kkjw).value) - eval('' + document.getElementById('E' + kjw).value)) * eval(Math.PI / 180.0));
    // Formula: θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
    thisaz=
    eval('' +
    Math.atan2(
    eval(
    Math.sin(deltalong) *
    Math.cos(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0)))
    ),
    eval(
    eval(
    Math.cos(eval(eval('' + document.getElementById('N' + kjw).value) * eval(Math.PI / 180.0))) *
    Math.sin(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0)))) -
    eval(
    Math.sin(eval(eval('' + document.getElementById('N' + kjw).value) * eval(Math.PI / 180.0))) *
    Math.cos(eval(eval('' + document.getElementById('N' + kkjw).value) * eval(Math.PI / 180.0))) *
    Math.cos(deltalong))
    )
    )) * eval(180.0 / Math.PI);
    if (thisaz < 0.0) { thisaz+=360.0; }
    document.getElementById('dE' + kjw).className='fatd';
    document.getElementById('dE' + kjw).innerHTML='' + thisaz + '';
    document.getElementById('dE' + kjw).title=dechange(document.getElementById('dE' + kjw).innerHTML, kjw, numlegs);
    document.getElementById('dN' + kjw).innerHTML='<font color=blue>' + great_circle_distance(eval('' + document.getElementById('E' + kjw).value), eval('' + document.getElementById('N' + kjw).value), eval('' + document.getElementById('E' + kkjw).value), eval('' + document.getElementById('N' + kkjw).value)) + '</font>';
    kjw++;
    kkjw++;
    }
    //document.title+=' ... ' + kjw;
    }
    }
  • Great Circle Distance …

    function great_circle_distance(talis, gnolis, latis, longis) {
    var ourdist=0.0;
    var rgnol=eval((gnolis) * Math.PI / 180.0);
    var rtal=eval((talis) * Math.PI / 180.0);
    var rlong=eval((longis) * Math.PI / 180.0);
    var rlat=eval((latis) * Math.PI / 180.0);
    var deltalong = Math.abs(eval(((gnolis)-(longis)) * Math.PI / 180.0));
    var acof = eval(Math.sin(rtal) * Math.sin(rlat)) + (Math.cos(rtal) * Math.cos(rlat) * Math.cos(deltalong)); // via //en.wikipedia.org/wiki/Great-circle_distance ... thanks
    //ourdist = eval(Math.round((Math.acos(acof) * 6371000.0) + 0.00001) * 100) / 100;
    ourdist = eval((Math.acos(acof) * 6371000.0) + 0.00001);
    return ourdist;
    }

… that now gets incorporated into our changed SurveyTraverse.htm Geo Chart calling live run via DMS geographicals link.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

Up to and including yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial‘s web application’s CSV co-ordinate formats supported included …

  • grid Easting and Northing co-ordinates
  • geographical Latitude and LongitudeLongitude and Latitude decimal co-ordinates … and today we add onto that list …
  • geographical Latitude and LongitudeLongitude and Latitude DMS (degrees, minutes, seconds) co-ordinates

… that latter format popular with Wikipedia‘s geodata content, and many other sources too. We took some such Wikipedia content for Australia’s capital cities and fed it into a Sydney.csv

“31°57′8″S”,”115°51′32″E”,”Perth”
“34°55′44″S”,”138°36′4″E”,”Adelaide”
“12°26′17″S”,”130°50′28″E”,”Darwin”
“27°28′04″S”,”153°01′41″E”,”Brisbane”
“33°51′54″S”,”151°12′34″E”,”Sydney”
“35°17′35″S”,”149°07′37″E”,”Canberra”
“37°48′49″S”,”144°57′47″E”,”Melbourne”
“42°52′50″S”,”147°19′30″E”,”Hobart”

… and onto an execution using such DMS geographicals above …

… possible because of a new PHP function …

<?php

function dmscheck($inct) {

// "33°51′54″S","151°12′34″E","Sydney"
// "34°55′44″S","138°36′4″E","Adelaide"
$lathfound=false;
$longhfound=false;
$restb="";
$degstrone="";
$reststrone="";
$degstrtwo="";
$reststrtwo="";
$minstr="";
$isdms=false;
$secstr="";
$nextrestb="";
$minusstr="";
$hdrline="";
$spares="";
$ideg=-1;
$lastc="";
$outct=$inct;
$outbits=explode("°", $inct);
if (strpos(strtolower($outbits[0]), "latitude") !== false && strpos(strtolower($outbits[0]), "longitude") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "latitude") < strpos(strtolower($outbits[0]), "longitude")) {
$lathfound=true;
} else {
$longhfound=true;
}
} else if (strpos(strtolower($outbits[0]), "lat") !== false && strpos(strtolower($outbits[0]), "long") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "lat") < strpos(strtolower($outbits[0]), "long")) {
$lathfound=true;
} else {
$longhfound=true;
}
}


if (sizeof($outbits) <= 2 && $isdms) {
$outct=str_replace(".0", "°0", str_replace(".1", "°1", str_replace(".2", "°2", str_replace(".3", "°3", str_replace(".4", "°4", str_replace(".5", "°5", str_replace(".6", "°6", str_replace(".7", "°7", str_replace(".8", "°8", str_replace(".9", "°9", $inct))))))))));
$outbits=explode("°", $outct);
$outct=$inct;
}


if (sizeof($outbits) > 2) {


$reststrone=strtoupper(explode(",", $outbits[1])[0]);
$minusstr="";
if (strpos(strtoupper($reststrone), "W") !== false || strpos(strtoupper($reststrone), "S") !== false) {
$minusstr="-";
}
//echo "\n \$reststrone=" . $reststrone . " \$minusstr=" . $minusstr . "\n";
//$reststrtwo=strtoupper(explode(",", $outbits[1])[0]);
if (!$lathfound && !$longhfound) {
while (substr($outbits[0], $ideg, 1) <= '9' && substr($outbits[0], $ideg, 1) >= '0') {
//echo "substr(\$outbits[0], \$ideg, 1)=" . substr($outbits[0], $ideg, 1) . "\n";
$spares=$degstrone;
$degstrone=substr($outbits[0], $ideg, 1) . $spares;
$ideg--;
}
$ideg=-1;
while (substr($outbits[1], $ideg, 1) <= '9' && substr($outbits[1], $ideg, 1) >= '0') {
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1], $ideg, 1) . $spares;
$ideg--;
}
if (strpos($reststrone, "N") !== false || strpos($reststrone, "S") !== false) {
if ($degstrone <= 90.0) {
$hdrline="Latitude,Longitude,\n";
}
}
}


$outct=substr($outbits[0],0,(strlen($outbits[0]) - strlen($degstrone))) . $minusstr . $degstrone;
for ($iuyt=1; $iuyt<sizeof($outbits); $iuyt++) {

$minusstr="";
$restb=explode(",", $outbits[$iuyt])[0];
$nextrestb="";
if (sizeof($outbits) > (1 + $iuyt)) {
$nextrestb=explode(",", $outbits[1 + $iuyt])[0];
}
//echo "\n\$restb=" . $restb . "\n<br>";
$minstr="";
$secstr="";
$ideg=0;
if (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
$lastc=substr($restb, -1, 1);
if ($lastc != "'" && $lastc != '"') { $lastc=""; }
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if ($ideg >= 2) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
} else {
$minstr.=substr($restb, $ideg, 1);
}
$ideg++;
}
$ideg++;
while (!(substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0'))) {
$ideg++;
}
if (substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0')) {
//echo "\n secs found\n";
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
$ideg++;
}
}
}
if ($minstr == "") { $minstr="0"; }
if ($secstr == "") { $secstr="0"; }
echo "\$minstr=" . $minstr . " and \$secstr=" . $secstr . "\n";
if ($restb == "" || $ideg == 1) {
$outct.=".0" . $outbits[$iuyt];
} else if (strpos(strtoupper($nextrestb), "W") !== false || strpos(strtoupper($nextrestb), "S") !== false) {
$minusstr="-";
//echo "\n\$Minusstr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,substr($outbits[$iuyt],0,(strlen($outbits[$iuyt]) - strlen($degstrtwo))) . $minusstr . $degstrtwo);
} else {
//echo "\n\$MinusStr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,$outbits[$iuyt]);
}

$ideg=-1;
$degstrtwo="";
//$minusstr="";
if (sizeof($outbits) > (1 + $iuyt)) {
while (substr($outbits[1 + $iuyt], $ideg, 1) <= '9' && substr($outbits[1 + $iuyt], $ideg, 1) >= '0') {
//echo "Substr(\$outbits[1 + \$iuyt], \$ideg, 1)=" . substr($outbits[1 + $iuyt], $ideg, 1) . "\n";
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1 + $iuyt], $ideg, 1) . $spares;
$ideg--;
}
}

}


}


return $hdrline . $outct;
}

?>

… reflected in a modified “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run via DMS geographicals link.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

It’s been about a three day bugbear for us that ever since we introduced the possibility for geographical (ie. latitude, longitude) co-ordinate input data to do with yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial‘s Survey Traverse web application that we encouraged a default …

  • data (field or column) order of Latitude then Longitude for geographicals … yet …
  • data order is Easting then Northing for other co-ordinates (ie. grid co-ordinates)

… and yet, in “Survey Traverse land” this does a disservice to the bearings because comparing apples with apples …

  • Latitude corresponds almost totally with Northing
  • Longitude corresponds almost totally with Easting

… that almost, above, being reflective of the fact that large distance survey legs (most likely with geographical co-ordinate data input) involve significant curvature of the Earth, which is not catered for by terrestrial (as distinct from “geodetic”) Survey Traverse calculations usually involving smaller distances (as if on a flat grid/table).

And so, where the data input is coming from a CSV file the fairly self explanatory PHP …

<?php

// Start of global initializations

$reverseorder=false;
$reversesuffix="";

// End of global initializations
// Local function initializations

$foundwordlatitude=false;
$foundwordlongitude=false;
$under180=array(true, true);
$under90=array(true, true);

// Processing logic goes here
// End of processing

if (!$under180[0] || !$under180[1]) {
$reverseorder=$reverseorder;
} else if ($under90[0] && $under90[1]) {
if (!$foundwordlongitude) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else {
$reversesuffix="<br><br><br><br>";
}
} else if ($under90[0] && $under180[1]) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else if ($under180[0] && $under90[1]) {
$reverseorder=false;
$reversesuffix="<br><br><br><br>";
}

?>

… says …

  1. if either of numerical data columns 1 and 2 has a value greater than 180 the data is in “grid co-ordinates”, not “geographicals” … else …
  2. if numerical data columns 1 and 2 all have values less than or equal to 90 will, unless in header records “Latitude” precedes “Longitude”, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  3. if numerical data column 2 all has values less than or equal to 180 and if numerical data column 1 all has values less than or equal to 90, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  4. leave the geographical input data column order in that order so that column 2 is thought of as Longitude mapped to Easting and column 1 is thought of as Latitude mapped to Northing

A retweaked “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run link showing an example of logic step 2 above … as below …

egg111.csv

We afforded backward compatibility to our blog posting links below by adding header records and/or ([EmojiCodePointList]) to our CSVs …

Type
CSV
Link
Grid co-ordinates
no places
eg.csv
327500,672500
316500,662500
322500,677500
316500,672500
314500,674500
323500,670500
321500,674500
328500,670500
eg.csv
Grid co-ordinates
with places and one emoji
egp.csv
327500,672500,”Arthur’s Seat, (Fort)”
316500,662500,”Bavelaw Castle”
322500,677500,”Caroline Park”
316500,672500,”Castle Gogar”
314500,674500,”Cat Stane”
323500,670500,”Craig Ho (onetwosevenninefiveeightdotsixfivezerothreenine)
321500,674500,”Craigcrook Castle”
328500,670500,”Craigmillar Castle”
egp.csv
Geographical co-ordinates
with places (small distances)
egg.csv
Latitude,Longitude,Placename
32.7500,67.2500,”Arthur’s Seat, (Fort)”
31.6500,66.2500,”Bavelaw Castle”
32.2500,67.7500,”Caroline Park”
31.6500,67.2500,”Castle Gogar”
31.4500,67.4500,”Cat Stane”
32.3500,67.0500,”Craig Ho”
32.1500,67.4500,”Craigcrook Castle”
32.8500,67.0500,”Craigmillar Castle”
egg.csv (and egg0.csv reverses the column header record to Longitude,Latitude,Placename so that Map Chart pattern of places more resembles shape of the grid co-ordinate canvas looks and context)
Geographical co-ordinates
with places (large distances)
egg1.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Craig Ho”
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg1.csv
Geographical co-ordinates
with places (large distances, one emoji)
egg11.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg11.csv
Geographical co-ordinates
with places (large distances, one emoji)
today’s reversed step 2 example
egg111.csv
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg111.csv


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

Onto yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial‘s contextual themes we extend those ideas by linking …

… allowing a ([EmojiCodePointList]) delimited suffix to placenames literally “spelling out” the CodePoint necessary to define the emoji, an example [EmojiCodePointList] (for Surfers Paradise) being …


Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)

… ie. 🏖️ is &#127958;&#65039;

Recognizing such a ([EmojiCodePointList]) it is stripped from the web application’s understanding of what that placename is, after having made the Emoji definition changes, as defined by the user.

A further retweaked geo_chart.php Geo Chart interfacer (as called by unchanged “last changed” SurveyTraverse.htm) Geo Chart calling live run link with an improved Emoji context, is, again, worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

We thought to improve on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial conjoining of …

… it’s good to be able to use …

  • Emojis
  • Link Lines

… but the Link Lines, then, had limited “context”. But what if the Survey Traverse had a …

  • xx-large start point Emoji
  • x-large end point Emoji

? Yes, as you can read at this useful link the CSS for font-size has some useful and interesting settings we’d like to link into our Google Chart Geo Chart SVG text newly added “class”, as required …


function emojimaybe(jnentity, jnentwo, endtag) {
var jjj;
var xclass='';
var allnum=true, iu;
var inentity=jnentity;
var inentwo=jnentwo;
var classesare=['border','bcoly','cglow','glow','xxsmall','xsmall','xx-small','x-small','smaller','small','xxlarge','xlarge','xx-large','x-large','larger','large','tenp','twentyp','onefiftyp','fiftyp','twohundredp','threehundredp','fourhundredp','fivehundredp','sixhundredp'];

if (inentwo != '') {
if (inentwo.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentwo=inentwo.replace(inentwo.replace(/\_/g,' ').split(' ')[0], inentwo.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('Xclass=' + xclass);
for (iu=0; iu<inentwo.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentwo.indexOf('_') != -1) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
allnum=true;
xclass='';
if (inentity != '') {
if (inentity.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentity=inentity.replace(inentity.replace(/\_/g,' ').split(' ')[0], inentity.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('xclass=' + xclass);
for (iu=0; iu<inentity.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentity.indexOf('_') != -1) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
return endtag;
}

A retweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link with an improved context, is worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

The recent HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial had us catering for decimal latitude and longitude input data. Within the logic for this we could be using …

… the latter choice made when the distances involved in the Survey Traverse are large. That Geo Chart is both capable of being worked to show …

  • Emojis
  • Link Lines

… an offer too good to refuse, and you can read about at Google Geo Chart Co-ordinate Emojis Tutorial. Except, that is, if in the meantime, our inhouse Geo Chart interfacing PHP logic does not keep up with Google changes to the Geo Chart itself. And that sad scenario was our discovery then, and today we fix it up.

With any data scraping feeling third-party feeling logic that we need to do here, it is “the data” that is everything, and you’re first troubleshooting question should be …

Some thing that used to work no longer works. What has changed with the underlying data?

Our strategy here was to capture the outerHTML (ie. element contents) of geo_chart.php’s “chart_div” (div) element of a scenario that should involve emojis and/or link lines for a …

  • now scenario (which is easy via a Web Inspector -> Console -> point at “chart_div” -> two finger gesture Copy OuterHTML) … versus …
  • then scenario (which we scraped together scouring snippets of data from the past existing on this MacBook Pro) of a similar scenario

… and a few prudent carriage returns revealed to us the issue. We had assumed a first HTML defs element with ID “defs” but that was no longer the case, that change cutting off a whole lot of (PHP written out) Javascript logic making Emojis and Link Lines work with Geo Charts (given savvy user usage).

A tweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link, the work leading to this more obvious after viewing today’s animated GIF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

You might say the progress made in yesterday’s HTML and Javascript and CSS Survey Traverse CSV Co-ordinates Tutorial was …

  • inordinately complex … for …
  • not enough “gain”

… two criticisms we can live with, and today, we “eat into” the credibility of, on two fronts …

  1. we extend functionality, to include “placename” data … and …

  2. that very complexity is not all bad news, as the involvement of PHP and HTML data format is also “an opportunity” to arrange data (and delimitation) to our own programming arrangements

It is “an opportunity” to come out of the PHP with two numeric fields and up to one (ie. optional placename) string field for each <br> delimited HTML record (that <br> allowing for a one Javascript codeline achieving this (though this aspect is not new to today’s work)).

It is “an opportunity” to not involve string delimitation coming out of the PHP on its way to the parent HTML iframe via its “srcdoc” attribute. How can we arrange this? Well, helped out by the usefulness of this great link we constructed the PHP function …

<?php

function clean_csv_commas($csv, $indelimis) { // thanks to https://stackoverflow.com/questions/10739016/how-to-remove-commas-between-double-quotes-in-php
$until=true;
$qdelim = '"';
$bqdelim = "'";
$altbqdelim = "&apos;";
$comma = ',';
$altcomma = '&comma;';
$altqdelim = '&quot;';
$prevcomma=FALSE;
$aftcomma=FALSE;
if ($indelimis == "'") {
$qdelim=$indelimis;
$bqdelim='"';
$altqdelim = '&apos;';
$altbqdelim = '&quot;';
}
$len = strlen($csv);
$inside_block = FALSE;
$out='';
$rep='';
for ($i=0; $i<$len; $i++) {
if (ord($csv[$i]) < 32) {
$inside_block=FALSE;
$until=false;
} else if ($csv[$i] == $qdelim) {
if ($i == 0) {
$prevcomma=FALSE;
$inside_block=TRUE;
} else if (($i + 1) == $len) {
$aftcomma=FALSE;
$inside_block=FALSE;
} else {
if ($csv[-1 + $i] == ',' || ord($csv[-1 + $i]) < 32) { $prevcomma=TRUE; } else { $prevcomma=FALSE; }
if ($csv[1 + $i] == ',' || ord($csv[1 + $i]) < 32) { $aftcomma=TRUE; } else { $aftcomma=FALSE; }
if ($inside_block) {
if ($aftcomma) { $inside_block=FALSE; }
} else {
if ($prevcomma) { $inside_block=TRUE; }
}
}
}

//if ($until) {
// $rep.="\n" . $csv[$i] . " \$inside_block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
//}
if ($csv[$i] == $comma && $inside_block) {
if ($until) {
$rep.="\n" . $csv[$i] . " \$inside-block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
}
$out.=$altcomma;
} else if ($csv[$i] == $qdelim && $inside_block && !$aftcomma && !$prevcomma) {
$out.=$altqdelim;
} else if ($csv[$i] == $bqdelim && $inside_block) {
$out.=$altbqdelim;
} else {
$out.=$csv[$i];
}

}
if ($indelimis == "") {
//file_put_contents("zerocsv.xxx", $csv);
//file_put_contents("one_csv.xxx", $rep);
//file_put_contents("onecsv.xxx", $out);
$out=str_replace("'","",str_replace('"','',clean_csv_commas($out, "'")));
//file_put_contents("twocsv.xxx", $out);
}
return $out;
}

?>

… called in this way

<?php

if (isset($_GET['csvfile'])) {
$fname=str_replace("+"," ",urldecode($_GET['csvfile']));
$csvcont='';
if (strpos(strtolower($fname),"http") !== false) {
$csvcont=file_get_contents($fname);
} else if (file_exists($fname)) {
$csvcont=file_get_contents($fname);
}
//file_put_contents("threecsv.xxx", '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>');
echo '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>';
exit;
}

?>

… to replace any need for string delimitation (via ‘ or ” characters encasing any commas mapped to &comma; or fellow string delimiters to &quot; or &apos; respectively) with HTML Entity use …


var eoff=0.0;
var noff=0.0;
var envials=[];
var pvials=[];
if (window.localStorage) {
// 34,56,78,45 ... ,
// 34,56,"One",78,45,"Two" ... ,"
// "One",34,56,"Two",78,45 ... ",
var acontt=decodeURIComponent(('' + localStorage.getItem('en_st')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (acontt != '') { localStorage.removeItem('en_st'); }
//alert(acontt);
var minicom=[];
var endelim=',';
if (acontt.indexOf(',"') != -1 && acontt.indexOf('",') != -1) {
if (eval('' + acontt.indexOf('",')) < eval('' + acontt.indexOf(',"'))) {
endelim='",';
} else {
endelim=',"';
}
} else if (acontt.indexOf(',"') != -1) {
endelim=',"';
} else if (acontt.indexOf('",') != -1) {
endelim='",';
}
var pfirst=true;
var pyoullneverfindthis='';
var jxv=0;
var xenvials=acontt.split(endelim);
xenvials.push('');
for (var ixv=0; ixv<xenvials.length; ixv++) {
if (xenvials[ixv] != '') {
if (endelim == ',"') {
pvials.push(xenvials[eval(1 + ixv)].split('"')[0]);
if (xenvials[ixv].indexOf('",') != -1) { xenvials[ixv]=xenvials[ixv].replace(xenvials[ixv].split('",')[0] + '",',''); }
minicom=xenvials[ixv].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (endelim == '",') {
pvials.push(xenvials[ixv].split('"')[0]);
if (xenvials[eval(1 + ixv)].indexOf(',"') != -1) { xenvials[eval(1 + ixv)]=xenvials[eval(1 + ixv)].replace(',"' + xenvials[eval(1 + ixv)].split(',"')[0],''); }
minicom=xenvials[eval(1 + ixv)].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (('' + xenvials[ixv]).trim() != '' && ('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '') {
//alert('envials.push(' + xenvials[ixv] + ');');
envials.push(xenvials[ixv]);
} else if (('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != pyoullneverfindthis) {
//alert('pvials.push(' + xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"') + ')');
pvials.push(xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"'));
if (pfirst) {
pfirst=false;
pyoullneverfindthis='youllnever_find_this';
}
} else {
//alert('envials.push(' + xenvials[ixv] + ')');
envials.push(xenvials[ixv]);
}
pfirst=false;
}
}
}

… as exemplified by …

Originally 327500,672500,”Arthur’s Seat, (Fort)”
Out of the PHP <html><body onload=”parent.document.getElementById(‘ifcsv’).srcdoc = ‘<pre>327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)<br></pre>';”></body></html>
Via Parent Iframe body innerHTML 327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)
window.localStorage 327500,672500,Arthur’s Seat&comma; (Fort)
Finally
E N Placename
327500 672500 Arthur’s Seat, (Fort)

And we’d like to thank this great link for today’s tutorial’s testing CSV data as per egp.csv


327500,672500,"Arthur's Seat, (Fort)"
316500,662500,"Bavelaw Castle"
322500,677500,"Caroline Park"
316500,672500,"Castle Gogar"
314500,674500,"Cat Stane"
323500,670500,"Craig Ho"
321500,674500,"Craigcrook Castle"
328500,670500,"Craigmillar Castle"

… in our changed “sister” PHP SurveyTraverse.php code called by our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS Survey Traverse Canvas Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

Onto yesterday’s HTML and Javascript and CSS NSW State Survey Traverse Tutorial progress with our Survey Traverse web application functionality we wanted to augment …

  • the existent tabular data … with …
  • new canvas graphics to show the (Easting,Northing) co-ordinate sets of the Survey Traverse

… involving the collection of minimums and maximums Javascript “ifzeromakezero” function code changes …


var edone=false, ndone=false;
var maxe=-1.0, mine=-1.0, maxn=-1.0, minn=-1.0;


function ifzeromakezero(innum,e_or_n) {
var cinnum = innum.toString();
if (cinnum.indexOf("e-") != (0 - 1)) {
if (e_or_n == 1) {
if (!edone) {
mine=0.0;
maxe=0.0;
} else {
if (mine > 0.0) { mine=0.0; }
if (maxe < 0.0) { maxe=0.0; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=0.0; maxn=0.0; } else { if (minn > 0.0) { minn=0.0; }
if (maxn < 0.0) { maxn=0.0; } } ndone=true; }

return 0.000;
}
if (e_or_n == 1) {
if (!edone) {
mine=innum;
maxe=innum;
} else {
if (mine > innum) { mine=innum; }
if (maxe < innum) { maxe=innum; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=innum; maxn=innum; } else { if (minn > innum) { minn=innum; }
if (maxn < innum) { maxn=innum; } } ndone=true; }

return innum;
}

… and the canvas creation and line plotting, featuring (thanks to (linear gradients on canvas) ideas from this excellent link) canvas Javascript code …


document.getElementById('overlays').innerHTML+='<br><br><canvas style="background-color:#f0f0f0;border:2px dashed red;" height=' + eval(40 + eval('' + maxn) - eval('' + minn)) + ' width=' + eval(40 + eval('' + maxe) - eval('' + mine)) + ' id=mycanvas></canvas>';
setTimeout(postspanscheck, 5000);
var ele=document.getElementById('mycanvas');
var context=document.getElementById('mycanvas').getContext('2d');
var iz=0, mto=true, grad;

// var pts = [[0, 0, "red"], [0, 0, "green"], [0, 0, "blue"], [0, 0, "purple"], [0, 0, "olive"], [0, 0, "magenta"], [0, 0, "cyan"], [0, 0, "brown"], [0, 0, "black"], [0, 0, "pink"], [0, 0, "darkgreen"], [0, 0, "darkblue"], [0, 0, "darkorange"]];
var pts = [[0, 0, "red"], [0, 0, "orange"], [0, 0, "yellow"], [0, 0, "green"], [0, 0, "cyan"], [0, 0, "blue"], [0, 0, "violet"]];
var begin = pts[0];
var end = pts[1];

while (document.getElementById('E' + iz)) {
if (document.getElementById('E' + iz).value != '') {
if (mto) {
context.lineWidth = 6;
context.lineJoin = "round";
context.lineCap = "round";
//context.strokeStyle = "black";
context.beginPath();
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
} else {
end=pts[eval(1 + eval(iz % 5))];
end[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
end[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
grad = context.createLinearGradient(begin[0], begin[1], end[0], end[1]);
grad.addColorStop(0, begin[2]);
grad.addColorStop(1, end[2]);
context.strokeStyle = grad;
context.lineTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
context.stroke();
//context.strokeStyle = "black";
context.beginPath();
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
}
mto=false;
}
iz++;
}
}

… via our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS NSW State Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS NSW State Survey Traverse Co-ordinates Tutorial

HTML and Javascript and CSS NSW State Survey Traverse Tutorial

Yesterday’s HTML and Javascript and CSS Survey Traverse Co-ordinates Tutorial was kind of “mathematical” by nature. Today we add some realism.

This realism stems from the discovery of a NSW State Survey mark in the local area (to the right of today’s tutorial picture). Having a Land Surveying background, an indestructible looking survey mark is a joy to behold. The thing is though, when I was doing a Bachelor Of Surveying in the late 1970’s and early 1980’s, this survey mark was much more an object of awe than perhaps such a mark is to people, even me, today. Mystery surrounded it, it taking a visit to a government agency (NSW Titles Office), and no doubt some paperwork to match, would be required to find out anything about it, Land Surveyors at the very least curious about …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (in whatever ellipsoid of relevance)
  • Reduced Level (at whatever datum of relevance)

We decided on our iPhone to feed that SS46391 survey mark name into Google, thanks, and see what comes up, and discovered the “NSW Survey Marks” iOS app that we downloaded and spent a happy half hour “in a wooooorrrrrllllllddd of discovery and interest” (well, you had to be there).

You see, this app is just great! The information above is augmented by location Sketch Maps (that a Land Surveyor from the past would have created in the NSW Titles Office).

This way, in that half hour we looked for 3 survey marks in that local area, and gleaned their co-ordinates to come up with the …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (from the NSW Survey Marks app)
  • Bearings and Distances and theodolite Angles derived

… also shown in today’s tutorial picture … via our changed SurveyTraverse.html live run link, the changes concerning allowing both …

  • decimal degrees … as well as …
  • degrees, minutes and seconds (useful for setting an angle with a theodolite)

… for those aforesaid mentioned Angles and Bearings (with your compass or iPhone compass app).

Some of this “NSW Survey Marks” app’s workings can be viewed with today’s accompanying PDF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

Here is a tutorial showing some client-side basics in HTML and Javascript and CSS all in the one HTML file, to simplify concepts. The tutorial subject matter is a webpage to perform Survey Traverse calculations. A Survey Traverse is:

Traverse is a method in the field of surveying to establish control networks.[1] It is also used in geodesy. Traverse networks involve placing survey stations along a line or path of travel, and then using the previously surveyed points as a base for observing the next point. Traverse networks have many advantages, including:

Less reconnaissance and organization needed;
While in other systems, which may require the survey to be performed along a rigid polygon shape, the traverse can change to any shape and thus can accommodate a great deal of different terrains;
Only a few observations need to be taken at each station, whereas in other survey networks a great deal of angular and linear observations need to be made and considered;
Traverse networks are free of the strength of figure considerations that happen in triangular systems;
Scale error does not add up as the traverse is performed. Azimuth swing errors can also be reduced by increasing the distance between stations.

The traverse is more accurate than triangulateration[2] (a combined function of the triangulation and trilateration practice).[3]

Let’s see some simple HTML in action in a tutorial …

Link to HTML “spiritual home” … at W3Schools has many tutorials.
Link to Survey Traverse live run … here.
Link to Survey Traverse live run (additional Google Line Chart functionality) here.
Link to Survey Traverse information … from Wikipedia from which quote above comes.
Link to some downloadable HTML code … rename to SurveyTraverse.html which packages up a lot of Javascript and a little bit of CSS … or JaCvasScriptS … not sure whether this would ever catch on.
Link to some downloadable PHP programming code (additional Google Line Chart functionality) … rename to SurveyTraverse.php

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart DMS Tutorial

Up to and including yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial‘s web application’s CSV co-ordinate formats supported included …

  • grid Easting and Northing co-ordinates
  • geographical Latitude and LongitudeLongitude and Latitude decimal co-ordinates … and today we add onto that list …
  • geographical Latitude and LongitudeLongitude and Latitude DMS (degrees, minutes, seconds) co-ordinates

… that latter format popular with Wikipedia‘s geodata content, and many other sources too. We took some such Wikipedia content for Australia’s capital cities and fed it into a Sydney.csv

“31°57′8″S”,”115°51′32″E”,”Perth”
“34°55′44″S”,”138°36′4″E”,”Adelaide”
“12°26′17″S”,”130°50′28″E”,”Darwin”
“27°28′04″S”,”153°01′41″E”,”Brisbane”
“33°51′54″S”,”151°12′34″E”,”Sydney”
“35°17′35″S”,”149°07′37″E”,”Canberra”
“37°48′49″S”,”144°57′47″E”,”Melbourne”
“42°52′50″S”,”147°19′30″E”,”Hobart”

… and onto an execution using such DMS geographicals above …

… possible because of a new PHP function …

<?php

function dmscheck($inct) {

// "33°51′54″S","151°12′34″E","Sydney"
// "34°55′44″S","138°36′4″E","Adelaide"
$lathfound=false;
$longhfound=false;
$restb="";
$degstrone="";
$reststrone="";
$degstrtwo="";
$reststrtwo="";
$minstr="";
$isdms=false;
$secstr="";
$nextrestb="";
$minusstr="";
$hdrline="";
$spares="";
$ideg=-1;
$lastc="";
$outct=$inct;
$outbits=explode("°", $inct);
if (strpos(strtolower($outbits[0]), "latitude") !== false && strpos(strtolower($outbits[0]), "longitude") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "latitude") < strpos(strtolower($outbits[0]), "longitude")) {
$lathfound=true;
} else {
$longhfound=true;
}
} else if (strpos(strtolower($outbits[0]), "lat") !== false && strpos(strtolower($outbits[0]), "long") !== false) {
if (strpos(strtolower($outbits[0]), "dms") !== false || strpos(strtolower($outbits[0]), "mmss") !== false || (strpos(strtolower($outbits[0]), "minute") !== false && strpos(strtolower($outbits[0]), "second") !== false)) {
$isdms=true;
}
if (strpos(strtolower($outbits[0]), "lat") < strpos(strtolower($outbits[0]), "long")) {
$lathfound=true;
} else {
$longhfound=true;
}
}


if (sizeof($outbits) <= 2 && $isdms) {
$outct=str_replace(".0", "°0", str_replace(".1", "°1", str_replace(".2", "°2", str_replace(".3", "°3", str_replace(".4", "°4", str_replace(".5", "°5", str_replace(".6", "°6", str_replace(".7", "°7", str_replace(".8", "°8", str_replace(".9", "°9", $inct))))))))));
$outbits=explode("°", $outct);
$outct=$inct;
}


if (sizeof($outbits) > 2) {


$reststrone=strtoupper(explode(",", $outbits[1])[0]);
$minusstr="";
if (strpos(strtoupper($reststrone), "W") !== false || strpos(strtoupper($reststrone), "S") !== false) {
$minusstr="-";
}
//echo "\n \$reststrone=" . $reststrone . " \$minusstr=" . $minusstr . "\n";
//$reststrtwo=strtoupper(explode(",", $outbits[1])[0]);
if (!$lathfound && !$longhfound) {
while (substr($outbits[0], $ideg, 1) <= '9' && substr($outbits[0], $ideg, 1) >= '0') {
//echo "substr(\$outbits[0], \$ideg, 1)=" . substr($outbits[0], $ideg, 1) . "\n";
$spares=$degstrone;
$degstrone=substr($outbits[0], $ideg, 1) . $spares;
$ideg--;
}
$ideg=-1;
while (substr($outbits[1], $ideg, 1) <= '9' && substr($outbits[1], $ideg, 1) >= '0') {
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1], $ideg, 1) . $spares;
$ideg--;
}
if (strpos($reststrone, "N") !== false || strpos($reststrone, "S") !== false) {
if ($degstrone <= 90.0) {
$hdrline="Latitude,Longitude,\n";
}
}
}


$outct=substr($outbits[0],0,(strlen($outbits[0]) - strlen($degstrone))) . $minusstr . $degstrone;
for ($iuyt=1; $iuyt<sizeof($outbits); $iuyt++) {

$minusstr="";
$restb=explode(",", $outbits[$iuyt])[0];
$nextrestb="";
if (sizeof($outbits) > (1 + $iuyt)) {
$nextrestb=explode(",", $outbits[1 + $iuyt])[0];
}
//echo "\n\$restb=" . $restb . "\n<br>";
$minstr="";
$secstr="";
$ideg=0;
if (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
$lastc=substr($restb, -1, 1);
if ($lastc != "'" && $lastc != '"') { $lastc=""; }
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if ($ideg >= 2) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
} else {
$minstr.=substr($restb, $ideg, 1);
}
$ideg++;
}
$ideg++;
while (!(substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0'))) {
$ideg++;
}
if (substr(($restb . " "), $ideg, 1) == '.' || (substr(($restb . " "), $ideg, 1) <= '9' && substr(($restb . " "), $ideg, 1) >= '0')) {
//echo "\n secs found\n";
while (substr($restb, $ideg, 1) == '.' || (substr($restb, $ideg, 1) <= '9' && substr($restb, $ideg, 1) >= '0')) {
if (strlen($secstr) == 2 && substr($restb, $ideg, 1) != '.') {
$secstr.=".";
}
$secstr.=substr($restb, $ideg, 1);
$ideg++;
}
}
}
if ($minstr == "") { $minstr="0"; }
if ($secstr == "") { $secstr="0"; }
echo "\$minstr=" . $minstr . " and \$secstr=" . $secstr . "\n";
if ($restb == "" || $ideg == 1) {
$outct.=".0" . $outbits[$iuyt];
} else if (strpos(strtoupper($nextrestb), "W") !== false || strpos(strtoupper($nextrestb), "S") !== false) {
$minusstr="-";
//echo "\n\$Minusstr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,substr($outbits[$iuyt],0,(strlen($outbits[$iuyt]) - strlen($degstrtwo))) . $minusstr . $degstrtwo);
} else {
//echo "\n\$MinusStr=" . $minusstr . "\n \$restb=" . $restb . "\n \$degstrtwo=" . $degstrtwo . "\n<br>";
$outct.="." . str_replace($restb,explode('.',('' . ($minstr / 60.0 + $secstr / 3600.0 + 0.0000000001)))[1] . $lastc,$outbits[$iuyt]);
}

$ideg=-1;
$degstrtwo="";
//$minusstr="";
if (sizeof($outbits) > (1 + $iuyt)) {
while (substr($outbits[1 + $iuyt], $ideg, 1) <= '9' && substr($outbits[1 + $iuyt], $ideg, 1) >= '0') {
//echo "Substr(\$outbits[1 + \$iuyt], \$ideg, 1)=" . substr($outbits[1 + $iuyt], $ideg, 1) . "\n";
$spares=$degstrtwo;
$degstrtwo=substr($outbits[1 + $iuyt], $ideg, 1) . $spares;
$ideg--;
}
}

}


}


return $hdrline . $outct;
}

?>

… reflected in a modified “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run via DMS geographicals link.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

It’s been about a three day bugbear for us that ever since we introduced the possibility for geographical (ie. latitude, longitude) co-ordinate input data to do with yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial‘s Survey Traverse web application that we encouraged a default …

  • data (field or column) order of Latitude then Longitude for geographicals … yet …
  • data order is Easting then Northing for other co-ordinates (ie. grid co-ordinates)

… and yet, in “Survey Traverse land” this does a disservice to the bearings because comparing apples with apples …

  • Latitude corresponds almost totally with Northing
  • Longitude corresponds almost totally with Easting

… that almost, above, being reflective of the fact that large distance survey legs (most likely with geographical co-ordinate data input) involve significant curvature of the Earth, which is not catered for by terrestrial (as distinct from “geodetic”) Survey Traverse calculations usually involving smaller distances (as if on a flat grid/table).

And so, where the data input is coming from a CSV file the fairly self explanatory PHP …

<?php

// Start of global initializations

$reverseorder=false;
$reversesuffix="";

// End of global initializations
// Local function initializations

$foundwordlatitude=false;
$foundwordlongitude=false;
$under180=array(true, true);
$under90=array(true, true);

// Processing logic goes here
// End of processing

if (!$under180[0] || !$under180[1]) {
$reverseorder=$reverseorder;
} else if ($under90[0] && $under90[1]) {
if (!$foundwordlongitude) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else {
$reversesuffix="<br><br><br><br>";
}
} else if ($under90[0] && $under180[1]) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else if ($under180[0] && $under90[1]) {
$reverseorder=false;
$reversesuffix="<br><br><br><br>";
}

?>

… says …

  1. if either of numerical data columns 1 and 2 has a value greater than 180 the data is in “grid co-ordinates”, not “geographicals” … else …
  2. if numerical data columns 1 and 2 all have values less than or equal to 90 will, unless in header records “Latitude” precedes “Longitude”, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  3. if numerical data column 2 all has values less than or equal to 180 and if numerical data column 1 all has values less than or equal to 90, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  4. leave the geographical input data column order in that order so that column 2 is thought of as Longitude mapped to Easting and column 1 is thought of as Latitude mapped to Northing

A retweaked “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run link showing an example of logic step 2 above … as below …

egg111.csv

We afforded backward compatibility to our blog posting links below by adding header records and/or ([EmojiCodePointList]) to our CSVs …

Type
CSV
Link
Grid co-ordinates
no places
eg.csv
327500,672500
316500,662500
322500,677500
316500,672500
314500,674500
323500,670500
321500,674500
328500,670500
eg.csv
Grid co-ordinates
with places and one emoji
egp.csv
327500,672500,”Arthur’s Seat, (Fort)”
316500,662500,”Bavelaw Castle”
322500,677500,”Caroline Park”
316500,672500,”Castle Gogar”
314500,674500,”Cat Stane”
323500,670500,”Craig Ho (onetwosevenninefiveeightdotsixfivezerothreenine)
321500,674500,”Craigcrook Castle”
328500,670500,”Craigmillar Castle”
egp.csv
Geographical co-ordinates
with places (small distances)
egg.csv
Latitude,Longitude,Placename
32.7500,67.2500,”Arthur’s Seat, (Fort)”
31.6500,66.2500,”Bavelaw Castle”
32.2500,67.7500,”Caroline Park”
31.6500,67.2500,”Castle Gogar”
31.4500,67.4500,”Cat Stane”
32.3500,67.0500,”Craig Ho”
32.1500,67.4500,”Craigcrook Castle”
32.8500,67.0500,”Craigmillar Castle”
egg.csv (and egg0.csv reverses the column header record to Longitude,Latitude,Placename so that Map Chart pattern of places more resembles shape of the grid co-ordinate canvas looks and context)
Geographical co-ordinates
with places (large distances)
egg1.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Craig Ho”
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg1.csv
Geographical co-ordinates
with places (large distances, one emoji)
egg11.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg11.csv
Geographical co-ordinates
with places (large distances, one emoji)
today’s reversed step 2 example
egg111.csv
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg111.csv


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

Onto yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial‘s contextual themes we extend those ideas by linking …

… allowing a ([EmojiCodePointList]) delimited suffix to placenames literally “spelling out” the CodePoint necessary to define the emoji, an example [EmojiCodePointList] (for Surfers Paradise) being …


Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)

… ie. 🏖️ is &#127958;&#65039;

Recognizing such a ([EmojiCodePointList]) it is stripped from the web application’s understanding of what that placename is, after having made the Emoji definition changes, as defined by the user.

A further retweaked geo_chart.php Geo Chart interfacer (as called by unchanged “last changed” SurveyTraverse.htm) Geo Chart calling live run link with an improved Emoji context, is, again, worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

We thought to improve on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial conjoining of …

… it’s good to be able to use …

  • Emojis
  • Link Lines

… but the Link Lines, then, had limited “context”. But what if the Survey Traverse had a …

  • xx-large start point Emoji
  • x-large end point Emoji

? Yes, as you can read at this useful link the CSS for font-size has some useful and interesting settings we’d like to link into our Google Chart Geo Chart SVG text newly added “class”, as required …


function emojimaybe(jnentity, jnentwo, endtag) {
var jjj;
var xclass='';
var allnum=true, iu;
var inentity=jnentity;
var inentwo=jnentwo;
var classesare=['border','bcoly','cglow','glow','xxsmall','xsmall','xx-small','x-small','smaller','small','xxlarge','xlarge','xx-large','x-large','larger','large','tenp','twentyp','onefiftyp','fiftyp','twohundredp','threehundredp','fourhundredp','fivehundredp','sixhundredp'];

if (inentwo != '') {
if (inentwo.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentwo=inentwo.replace(inentwo.replace(/\_/g,' ').split(' ')[0], inentwo.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('Xclass=' + xclass);
for (iu=0; iu<inentwo.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentwo.indexOf('_') != -1) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
allnum=true;
xclass='';
if (inentity != '') {
if (inentity.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentity=inentity.replace(inentity.replace(/\_/g,' ').split(' ')[0], inentity.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('xclass=' + xclass);
for (iu=0; iu<inentity.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentity.indexOf('_') != -1) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
return endtag;
}

A retweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link with an improved context, is worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

The recent HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial had us catering for decimal latitude and longitude input data. Within the logic for this we could be using …

… the latter choice made when the distances involved in the Survey Traverse are large. That Geo Chart is both capable of being worked to show …

  • Emojis
  • Link Lines

… an offer too good to refuse, and you can read about at Google Geo Chart Co-ordinate Emojis Tutorial. Except, that is, if in the meantime, our inhouse Geo Chart interfacing PHP logic does not keep up with Google changes to the Geo Chart itself. And that sad scenario was our discovery then, and today we fix it up.

With any data scraping feeling third-party feeling logic that we need to do here, it is “the data” that is everything, and you’re first troubleshooting question should be …

Some thing that used to work no longer works. What has changed with the underlying data?

Our strategy here was to capture the outerHTML (ie. element contents) of geo_chart.php’s “chart_div” (div) element of a scenario that should involve emojis and/or link lines for a …

  • now scenario (which is easy via a Web Inspector -> Console -> point at “chart_div” -> two finger gesture Copy OuterHTML) … versus …
  • then scenario (which we scraped together scouring snippets of data from the past existing on this MacBook Pro) of a similar scenario

… and a few prudent carriage returns revealed to us the issue. We had assumed a first HTML defs element with ID “defs” but that was no longer the case, that change cutting off a whole lot of (PHP written out) Javascript logic making Emojis and Link Lines work with Geo Charts (given savvy user usage).

A tweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link, the work leading to this more obvious after viewing today’s animated GIF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

You might say the progress made in yesterday’s HTML and Javascript and CSS Survey Traverse CSV Co-ordinates Tutorial was …

  • inordinately complex … for …
  • not enough “gain”

… two criticisms we can live with, and today, we “eat into” the credibility of, on two fronts …

  1. we extend functionality, to include “placename” data … and …

  2. that very complexity is not all bad news, as the involvement of PHP and HTML data format is also “an opportunity” to arrange data (and delimitation) to our own programming arrangements

It is “an opportunity” to come out of the PHP with two numeric fields and up to one (ie. optional placename) string field for each <br> delimited HTML record (that <br> allowing for a one Javascript codeline achieving this (though this aspect is not new to today’s work)).

It is “an opportunity” to not involve string delimitation coming out of the PHP on its way to the parent HTML iframe via its “srcdoc” attribute. How can we arrange this? Well, helped out by the usefulness of this great link we constructed the PHP function …

<?php

function clean_csv_commas($csv, $indelimis) { // thanks to https://stackoverflow.com/questions/10739016/how-to-remove-commas-between-double-quotes-in-php
$until=true;
$qdelim = '"';
$bqdelim = "'";
$altbqdelim = "&apos;";
$comma = ',';
$altcomma = '&comma;';
$altqdelim = '&quot;';
$prevcomma=FALSE;
$aftcomma=FALSE;
if ($indelimis == "'") {
$qdelim=$indelimis;
$bqdelim='"';
$altqdelim = '&apos;';
$altbqdelim = '&quot;';
}
$len = strlen($csv);
$inside_block = FALSE;
$out='';
$rep='';
for ($i=0; $i<$len; $i++) {
if (ord($csv[$i]) < 32) {
$inside_block=FALSE;
$until=false;
} else if ($csv[$i] == $qdelim) {
if ($i == 0) {
$prevcomma=FALSE;
$inside_block=TRUE;
} else if (($i + 1) == $len) {
$aftcomma=FALSE;
$inside_block=FALSE;
} else {
if ($csv[-1 + $i] == ',' || ord($csv[-1 + $i]) < 32) { $prevcomma=TRUE; } else { $prevcomma=FALSE; }
if ($csv[1 + $i] == ',' || ord($csv[1 + $i]) < 32) { $aftcomma=TRUE; } else { $aftcomma=FALSE; }
if ($inside_block) {
if ($aftcomma) { $inside_block=FALSE; }
} else {
if ($prevcomma) { $inside_block=TRUE; }
}
}
}

//if ($until) {
// $rep.="\n" . $csv[$i] . " \$inside_block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
//}
if ($csv[$i] == $comma && $inside_block) {
if ($until) {
$rep.="\n" . $csv[$i] . " \$inside-block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
}
$out.=$altcomma;
} else if ($csv[$i] == $qdelim && $inside_block && !$aftcomma && !$prevcomma) {
$out.=$altqdelim;
} else if ($csv[$i] == $bqdelim && $inside_block) {
$out.=$altbqdelim;
} else {
$out.=$csv[$i];
}

}
if ($indelimis == "") {
//file_put_contents("zerocsv.xxx", $csv);
//file_put_contents("one_csv.xxx", $rep);
//file_put_contents("onecsv.xxx", $out);
$out=str_replace("'","",str_replace('"','',clean_csv_commas($out, "'")));
//file_put_contents("twocsv.xxx", $out);
}
return $out;
}

?>

… called in this way

<?php

if (isset($_GET['csvfile'])) {
$fname=str_replace("+"," ",urldecode($_GET['csvfile']));
$csvcont='';
if (strpos(strtolower($fname),"http") !== false) {
$csvcont=file_get_contents($fname);
} else if (file_exists($fname)) {
$csvcont=file_get_contents($fname);
}
//file_put_contents("threecsv.xxx", '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>');
echo '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>';
exit;
}

?>

… to replace any need for string delimitation (via ‘ or ” characters encasing any commas mapped to &comma; or fellow string delimiters to &quot; or &apos; respectively) with HTML Entity use …


var eoff=0.0;
var noff=0.0;
var envials=[];
var pvials=[];
if (window.localStorage) {
// 34,56,78,45 ... ,
// 34,56,"One",78,45,"Two" ... ,"
// "One",34,56,"Two",78,45 ... ",
var acontt=decodeURIComponent(('' + localStorage.getItem('en_st')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (acontt != '') { localStorage.removeItem('en_st'); }
//alert(acontt);
var minicom=[];
var endelim=',';
if (acontt.indexOf(',"') != -1 && acontt.indexOf('",') != -1) {
if (eval('' + acontt.indexOf('",')) < eval('' + acontt.indexOf(',"'))) {
endelim='",';
} else {
endelim=',"';
}
} else if (acontt.indexOf(',"') != -1) {
endelim=',"';
} else if (acontt.indexOf('",') != -1) {
endelim='",';
}
var pfirst=true;
var pyoullneverfindthis='';
var jxv=0;
var xenvials=acontt.split(endelim);
xenvials.push('');
for (var ixv=0; ixv<xenvials.length; ixv++) {
if (xenvials[ixv] != '') {
if (endelim == ',"') {
pvials.push(xenvials[eval(1 + ixv)].split('"')[0]);
if (xenvials[ixv].indexOf('",') != -1) { xenvials[ixv]=xenvials[ixv].replace(xenvials[ixv].split('",')[0] + '",',''); }
minicom=xenvials[ixv].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (endelim == '",') {
pvials.push(xenvials[ixv].split('"')[0]);
if (xenvials[eval(1 + ixv)].indexOf(',"') != -1) { xenvials[eval(1 + ixv)]=xenvials[eval(1 + ixv)].replace(',"' + xenvials[eval(1 + ixv)].split(',"')[0],''); }
minicom=xenvials[eval(1 + ixv)].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (('' + xenvials[ixv]).trim() != '' && ('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '') {
//alert('envials.push(' + xenvials[ixv] + ');');
envials.push(xenvials[ixv]);
} else if (('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != pyoullneverfindthis) {
//alert('pvials.push(' + xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"') + ')');
pvials.push(xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"'));
if (pfirst) {
pfirst=false;
pyoullneverfindthis='youllnever_find_this';
}
} else {
//alert('envials.push(' + xenvials[ixv] + ')');
envials.push(xenvials[ixv]);
}
pfirst=false;
}
}
}

… as exemplified by …

Originally 327500,672500,”Arthur’s Seat, (Fort)”
Out of the PHP <html><body onload=”parent.document.getElementById(‘ifcsv’).srcdoc = ‘<pre>327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)<br></pre>';”></body></html>
Via Parent Iframe body innerHTML 327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)
window.localStorage 327500,672500,Arthur’s Seat&comma; (Fort)
Finally
E N Placename
327500 672500 Arthur’s Seat, (Fort)

And we’d like to thank this great link for today’s tutorial’s testing CSV data as per egp.csv


327500,672500,"Arthur's Seat, (Fort)"
316500,662500,"Bavelaw Castle"
322500,677500,"Caroline Park"
316500,672500,"Castle Gogar"
314500,674500,"Cat Stane"
323500,670500,"Craig Ho"
321500,674500,"Craigcrook Castle"
328500,670500,"Craigmillar Castle"

… in our changed “sister” PHP SurveyTraverse.php code called by our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS Survey Traverse Canvas Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

Onto yesterday’s HTML and Javascript and CSS NSW State Survey Traverse Tutorial progress with our Survey Traverse web application functionality we wanted to augment …

  • the existent tabular data … with …
  • new canvas graphics to show the (Easting,Northing) co-ordinate sets of the Survey Traverse

… involving the collection of minimums and maximums Javascript “ifzeromakezero” function code changes …


var edone=false, ndone=false;
var maxe=-1.0, mine=-1.0, maxn=-1.0, minn=-1.0;


function ifzeromakezero(innum,e_or_n) {
var cinnum = innum.toString();
if (cinnum.indexOf("e-") != (0 - 1)) {
if (e_or_n == 1) {
if (!edone) {
mine=0.0;
maxe=0.0;
} else {
if (mine > 0.0) { mine=0.0; }
if (maxe < 0.0) { maxe=0.0; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=0.0; maxn=0.0; } else { if (minn > 0.0) { minn=0.0; }
if (maxn < 0.0) { maxn=0.0; } } ndone=true; }

return 0.000;
}
if (e_or_n == 1) {
if (!edone) {
mine=innum;
maxe=innum;
} else {
if (mine > innum) { mine=innum; }
if (maxe < innum) { maxe=innum; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=innum; maxn=innum; } else { if (minn > innum) { minn=innum; }
if (maxn < innum) { maxn=innum; } } ndone=true; }

return innum;
}

… and the canvas creation and line plotting, featuring (thanks to (linear gradients on canvas) ideas from this excellent link) canvas Javascript code …


document.getElementById('overlays').innerHTML+='<br><br><canvas style="background-color:#f0f0f0;border:2px dashed red;" height=' + eval(40 + eval('' + maxn) - eval('' + minn)) + ' width=' + eval(40 + eval('' + maxe) - eval('' + mine)) + ' id=mycanvas></canvas>';
setTimeout(postspanscheck, 5000);
var ele=document.getElementById('mycanvas');
var context=document.getElementById('mycanvas').getContext('2d');
var iz=0, mto=true, grad;

// var pts = [[0, 0, "red"], [0, 0, "green"], [0, 0, "blue"], [0, 0, "purple"], [0, 0, "olive"], [0, 0, "magenta"], [0, 0, "cyan"], [0, 0, "brown"], [0, 0, "black"], [0, 0, "pink"], [0, 0, "darkgreen"], [0, 0, "darkblue"], [0, 0, "darkorange"]];
var pts = [[0, 0, "red"], [0, 0, "orange"], [0, 0, "yellow"], [0, 0, "green"], [0, 0, "cyan"], [0, 0, "blue"], [0, 0, "violet"]];
var begin = pts[0];
var end = pts[1];

while (document.getElementById('E' + iz)) {
if (document.getElementById('E' + iz).value != '') {
if (mto) {
context.lineWidth = 6;
context.lineJoin = "round";
context.lineCap = "round";
//context.strokeStyle = "black";
context.beginPath();
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
} else {
end=pts[eval(1 + eval(iz % 5))];
end[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
end[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
grad = context.createLinearGradient(begin[0], begin[1], end[0], end[1]);
grad.addColorStop(0, begin[2]);
grad.addColorStop(1, end[2]);
context.strokeStyle = grad;
context.lineTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
context.stroke();
//context.strokeStyle = "black";
context.beginPath();
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
}
mto=false;
}
iz++;
}
}

… via our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS NSW State Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS NSW State Survey Traverse Co-ordinates Tutorial

HTML and Javascript and CSS NSW State Survey Traverse Tutorial

Yesterday’s HTML and Javascript and CSS Survey Traverse Co-ordinates Tutorial was kind of “mathematical” by nature. Today we add some realism.

This realism stems from the discovery of a NSW State Survey mark in the local area (to the right of today’s tutorial picture). Having a Land Surveying background, an indestructible looking survey mark is a joy to behold. The thing is though, when I was doing a Bachelor Of Surveying in the late 1970’s and early 1980’s, this survey mark was much more an object of awe than perhaps such a mark is to people, even me, today. Mystery surrounded it, it taking a visit to a government agency (NSW Titles Office), and no doubt some paperwork to match, would be required to find out anything about it, Land Surveyors at the very least curious about …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (in whatever ellipsoid of relevance)
  • Reduced Level (at whatever datum of relevance)

We decided on our iPhone to feed that SS46391 survey mark name into Google, thanks, and see what comes up, and discovered the “NSW Survey Marks” iOS app that we downloaded and spent a happy half hour “in a wooooorrrrrllllllddd of discovery and interest” (well, you had to be there).

You see, this app is just great! The information above is augmented by location Sketch Maps (that a Land Surveyor from the past would have created in the NSW Titles Office).

This way, in that half hour we looked for 3 survey marks in that local area, and gleaned their co-ordinates to come up with the …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (from the NSW Survey Marks app)
  • Bearings and Distances and theodolite Angles derived

… also shown in today’s tutorial picture … via our changed SurveyTraverse.html live run link, the changes concerning allowing both …

  • decimal degrees … as well as …
  • degrees, minutes and seconds (useful for setting an angle with a theodolite)

… for those aforesaid mentioned Angles and Bearings (with your compass or iPhone compass app).

Some of this “NSW Survey Marks” app’s workings can be viewed with today’s accompanying PDF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

Here is a tutorial showing some client-side basics in HTML and Javascript and CSS all in the one HTML file, to simplify concepts. The tutorial subject matter is a webpage to perform Survey Traverse calculations. A Survey Traverse is:

Traverse is a method in the field of surveying to establish control networks.[1] It is also used in geodesy. Traverse networks involve placing survey stations along a line or path of travel, and then using the previously surveyed points as a base for observing the next point. Traverse networks have many advantages, including:

Less reconnaissance and organization needed;
While in other systems, which may require the survey to be performed along a rigid polygon shape, the traverse can change to any shape and thus can accommodate a great deal of different terrains;
Only a few observations need to be taken at each station, whereas in other survey networks a great deal of angular and linear observations need to be made and considered;
Traverse networks are free of the strength of figure considerations that happen in triangular systems;
Scale error does not add up as the traverse is performed. Azimuth swing errors can also be reduced by increasing the distance between stations.

The traverse is more accurate than triangulateration[2] (a combined function of the triangulation and trilateration practice).[3]

Let’s see some simple HTML in action in a tutorial …

Link to HTML “spiritual home” … at W3Schools has many tutorials.
Link to Survey Traverse live run … here.
Link to Survey Traverse live run (additional Google Line Chart functionality) here.
Link to Survey Traverse information … from Wikipedia from which quote above comes.
Link to some downloadable HTML code … rename to SurveyTraverse.html which packages up a lot of Javascript and a little bit of CSS … or JaCvasScriptS … not sure whether this would ever catch on.
Link to some downloadable PHP programming code (additional Google Line Chart functionality) … rename to SurveyTraverse.php

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Land Surveying, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Order Tutorial

It’s been about a three day bugbear for us that ever since we introduced the possibility for geographical (ie. latitude, longitude) co-ordinate input data to do with yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial‘s Survey Traverse web application that we encouraged a default …

  • data (field or column) order of Latitude then Longitude for geographicals … yet …
  • data order is Easting then Northing for other co-ordinates (ie. grid co-ordinates)

… and yet, in “Survey Traverse land” this does a disservice to the bearings because comparing apples with apples …

  • Latitude corresponds almost totally with Northing
  • Longitude corresponds almost totally with Easting

… that almost, above, being reflective of the fact that large distance survey legs (most likely with geographical co-ordinate data input) involve significant curvature of the Earth, which is not catered for by terrestrial (as distinct from “geodetic”) Survey Traverse calculations usually involving smaller distances (as if on a flat grid/table).

And so, where the data input is coming from a CSV file the fairly self explanatory PHP …

<?php

// Start of global initializations

$reverseorder=false;
$reversesuffix="";

// End of global initializations
// Local function initializations

$foundwordlatitude=false;
$foundwordlongitude=false;
$under180=array(true, true);
$under90=array(true, true);

// Processing logic goes here
// End of processing

if (!$under180[0] || !$under180[1]) {
$reverseorder=$reverseorder;
} else if ($under90[0] && $under90[1]) {
if (!$foundwordlongitude) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else {
$reversesuffix="<br><br><br><br>";
}
} else if ($under90[0] && $under180[1]) {
$reverseorder=true;
$reversesuffix="<pre></pre>";
} else if ($under180[0] && $under90[1]) {
$reverseorder=false;
$reversesuffix="<br><br><br><br>";
}

?>

… says …

  1. if either of numerical data columns 1 and 2 has a value greater than 180 the data is in “grid co-ordinates”, not “geographicals” … else …
  2. if numerical data columns 1 and 2 all have values less than or equal to 90 will, unless in header records “Latitude” precedes “Longitude”, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  3. if numerical data column 2 all has values less than or equal to 180 and if numerical data column 1 all has values less than or equal to 90, we will “reverse” the order so that column 1 is thought of as Longitude mapped to Easting and column 2 is thought of as Latitude mapped to Northing … else …
  4. leave the geographical input data column order in that order so that column 2 is thought of as Longitude mapped to Easting and column 1 is thought of as Latitude mapped to Northing

A retweaked “sister” PHP SurveyTraverse.php PHP helper called by our changed SurveyTraverse.htm Geo Chart calling live run link showing an example of logic step 2 above … as below …

We afforded backward compatibility to our blog posting links below by adding header records and/or ([EmojiCodePointList]) to our CSVs …

Type
CSV
Link
Grid co-ordinates
no places
eg.csv
327500,672500
316500,662500
322500,677500
316500,672500
314500,674500
323500,670500
321500,674500
328500,670500
eg.csv
Grid co-ordinates
with places and one emoji
egp.csv
327500,672500,”Arthur’s Seat, (Fort)”
316500,662500,”Bavelaw Castle”
322500,677500,”Caroline Park”
316500,672500,”Castle Gogar”
314500,674500,”Cat Stane”
323500,670500,”Craig Ho (onetwosevenninefiveeightdotsixfivezerothreenine)
321500,674500,”Craigcrook Castle”
328500,670500,”Craigmillar Castle”
egp.csv
Geographical co-ordinates
with places (small distances)
egg.csv
Latitude,Longitude,Placename
32.7500,67.2500,”Arthur’s Seat, (Fort)”
31.6500,66.2500,”Bavelaw Castle”
32.2500,67.7500,”Caroline Park”
31.6500,67.2500,”Castle Gogar”
31.4500,67.4500,”Cat Stane”
32.3500,67.0500,”Craig Ho”
32.1500,67.4500,”Craigcrook Castle”
32.8500,67.0500,”Craigmillar Castle”
egg.csv (and egg0.csv reverses the column header record to Longitude,Latitude,Placename so that Map Chart pattern of places more resembles shape of the grid co-ordinate canvas looks and context)
Geographical co-ordinates
with places (large distances)
egg1.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Craig Ho”
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg1.csv
Geographical co-ordinates
with places (large distances, one emoji)
egg11.csv
Latitude,Longitude,Place
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg11.csv
Geographical co-ordinates
with places (large distances, one emoji)
today’s reversed step 2 example
egg111.csv
32.7500,67.2500,”Arthur’s Seat, (Fort)”
41.6500,66.2500,”Bavelaw Castle”
52.2500,68.7500,”Caroline Park”
61.6500,60.2500,”Castle Gogar”
21.4500,61.4500,”Cat Stane”
12.3500,63.0500,”Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)
22.1500,64.4500,”Craigcrook Castle”
72.8500,65.0500,”Craigmillar Castle”
egg111.csv


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

Onto yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial‘s contextual themes we extend those ideas by linking …

… allowing a ([EmojiCodePointList]) delimited suffix to placenames literally “spelling out” the CodePoint necessary to define the emoji, an example [EmojiCodePointList] (for Surfers Paradise) being …


Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)

… ie. 🏖️ is &#127958;&#65039;

Recognizing such a ([EmojiCodePointList]) it is stripped from the web application’s understanding of what that placename is, after having made the Emoji definition changes, as defined by the user.

A further retweaked geo_chart.php Geo Chart interfacer (as called by unchanged “last changed” SurveyTraverse.htm) Geo Chart calling live run link with an improved Emoji context, is, again, worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

We thought to improve on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial conjoining of …

… it’s good to be able to use …

  • Emojis
  • Link Lines

… but the Link Lines, then, had limited “context”. But what if the Survey Traverse had a …

  • xx-large start point Emoji
  • x-large end point Emoji

? Yes, as you can read at this useful link the CSS for font-size has some useful and interesting settings we’d like to link into our Google Chart Geo Chart SVG text newly added “class”, as required …


function emojimaybe(jnentity, jnentwo, endtag) {
var jjj;
var xclass='';
var allnum=true, iu;
var inentity=jnentity;
var inentwo=jnentwo;
var classesare=['border','bcoly','cglow','glow','xxsmall','xsmall','xx-small','x-small','smaller','small','xxlarge','xlarge','xx-large','x-large','larger','large','tenp','twentyp','onefiftyp','fiftyp','twohundredp','threehundredp','fourhundredp','fivehundredp','sixhundredp'];

if (inentwo != '') {
if (inentwo.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentwo=inentwo.replace(inentwo.replace(/\_/g,' ').split(' ')[0], inentwo.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('Xclass=' + xclass);
for (iu=0; iu<inentwo.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentwo.indexOf('_') != -1) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
allnum=true;
xclass='';
if (inentity != '') {
if (inentity.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentity=inentity.replace(inentity.replace(/\_/g,' ').split(' ')[0], inentity.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('xclass=' + xclass);
for (iu=0; iu<inentity.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentity.indexOf('_') != -1) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
return endtag;
}

A retweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link with an improved context, is worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

The recent HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial had us catering for decimal latitude and longitude input data. Within the logic for this we could be using …

… the latter choice made when the distances involved in the Survey Traverse are large. That Geo Chart is both capable of being worked to show …

  • Emojis
  • Link Lines

… an offer too good to refuse, and you can read about at Google Geo Chart Co-ordinate Emojis Tutorial. Except, that is, if in the meantime, our inhouse Geo Chart interfacing PHP logic does not keep up with Google changes to the Geo Chart itself. And that sad scenario was our discovery then, and today we fix it up.

With any data scraping feeling third-party feeling logic that we need to do here, it is “the data” that is everything, and you’re first troubleshooting question should be …

Some thing that used to work no longer works. What has changed with the underlying data?

Our strategy here was to capture the outerHTML (ie. element contents) of geo_chart.php’s “chart_div” (div) element of a scenario that should involve emojis and/or link lines for a …

  • now scenario (which is easy via a Web Inspector -> Console -> point at “chart_div” -> two finger gesture Copy OuterHTML) … versus …
  • then scenario (which we scraped together scouring snippets of data from the past existing on this MacBook Pro) of a similar scenario

… and a few prudent carriage returns revealed to us the issue. We had assumed a first HTML defs element with ID “defs” but that was no longer the case, that change cutting off a whole lot of (PHP written out) Javascript logic making Emojis and Link Lines work with Geo Charts (given savvy user usage).

A tweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link, the work leading to this more obvious after viewing today’s animated GIF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

You might say the progress made in yesterday’s HTML and Javascript and CSS Survey Traverse CSV Co-ordinates Tutorial was …

  • inordinately complex … for …
  • not enough “gain”

… two criticisms we can live with, and today, we “eat into” the credibility of, on two fronts …

  1. we extend functionality, to include “placename” data … and …

  2. that very complexity is not all bad news, as the involvement of PHP and HTML data format is also “an opportunity” to arrange data (and delimitation) to our own programming arrangements

It is “an opportunity” to come out of the PHP with two numeric fields and up to one (ie. optional placename) string field for each <br> delimited HTML record (that <br> allowing for a one Javascript codeline achieving this (though this aspect is not new to today’s work)).

It is “an opportunity” to not involve string delimitation coming out of the PHP on its way to the parent HTML iframe via its “srcdoc” attribute. How can we arrange this? Well, helped out by the usefulness of this great link we constructed the PHP function …

<?php

function clean_csv_commas($csv, $indelimis) { // thanks to https://stackoverflow.com/questions/10739016/how-to-remove-commas-between-double-quotes-in-php
$until=true;
$qdelim = '"';
$bqdelim = "'";
$altbqdelim = "&apos;";
$comma = ',';
$altcomma = '&comma;';
$altqdelim = '&quot;';
$prevcomma=FALSE;
$aftcomma=FALSE;
if ($indelimis == "'") {
$qdelim=$indelimis;
$bqdelim='"';
$altqdelim = '&apos;';
$altbqdelim = '&quot;';
}
$len = strlen($csv);
$inside_block = FALSE;
$out='';
$rep='';
for ($i=0; $i<$len; $i++) {
if (ord($csv[$i]) < 32) {
$inside_block=FALSE;
$until=false;
} else if ($csv[$i] == $qdelim) {
if ($i == 0) {
$prevcomma=FALSE;
$inside_block=TRUE;
} else if (($i + 1) == $len) {
$aftcomma=FALSE;
$inside_block=FALSE;
} else {
if ($csv[-1 + $i] == ',' || ord($csv[-1 + $i]) < 32) { $prevcomma=TRUE; } else { $prevcomma=FALSE; }
if ($csv[1 + $i] == ',' || ord($csv[1 + $i]) < 32) { $aftcomma=TRUE; } else { $aftcomma=FALSE; }
if ($inside_block) {
if ($aftcomma) { $inside_block=FALSE; }
} else {
if ($prevcomma) { $inside_block=TRUE; }
}
}
}

//if ($until) {
// $rep.="\n" . $csv[$i] . " \$inside_block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
//}
if ($csv[$i] == $comma && $inside_block) {
if ($until) {
$rep.="\n" . $csv[$i] . " \$inside-block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
}
$out.=$altcomma;
} else if ($csv[$i] == $qdelim && $inside_block && !$aftcomma && !$prevcomma) {
$out.=$altqdelim;
} else if ($csv[$i] == $bqdelim && $inside_block) {
$out.=$altbqdelim;
} else {
$out.=$csv[$i];
}

}
if ($indelimis == "") {
//file_put_contents("zerocsv.xxx", $csv);
//file_put_contents("one_csv.xxx", $rep);
//file_put_contents("onecsv.xxx", $out);
$out=str_replace("'","",str_replace('"','',clean_csv_commas($out, "'")));
//file_put_contents("twocsv.xxx", $out);
}
return $out;
}

?>

… called in this way

<?php

if (isset($_GET['csvfile'])) {
$fname=str_replace("+"," ",urldecode($_GET['csvfile']));
$csvcont='';
if (strpos(strtolower($fname),"http") !== false) {
$csvcont=file_get_contents($fname);
} else if (file_exists($fname)) {
$csvcont=file_get_contents($fname);
}
//file_put_contents("threecsv.xxx", '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>');
echo '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>';
exit;
}

?>

… to replace any need for string delimitation (via ‘ or ” characters encasing any commas mapped to &comma; or fellow string delimiters to &quot; or &apos; respectively) with HTML Entity use …


var eoff=0.0;
var noff=0.0;
var envials=[];
var pvials=[];
if (window.localStorage) {
// 34,56,78,45 ... ,
// 34,56,"One",78,45,"Two" ... ,"
// "One",34,56,"Two",78,45 ... ",
var acontt=decodeURIComponent(('' + localStorage.getItem('en_st')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (acontt != '') { localStorage.removeItem('en_st'); }
//alert(acontt);
var minicom=[];
var endelim=',';
if (acontt.indexOf(',"') != -1 && acontt.indexOf('",') != -1) {
if (eval('' + acontt.indexOf('",')) < eval('' + acontt.indexOf(',"'))) {
endelim='",';
} else {
endelim=',"';
}
} else if (acontt.indexOf(',"') != -1) {
endelim=',"';
} else if (acontt.indexOf('",') != -1) {
endelim='",';
}
var pfirst=true;
var pyoullneverfindthis='';
var jxv=0;
var xenvials=acontt.split(endelim);
xenvials.push('');
for (var ixv=0; ixv<xenvials.length; ixv++) {
if (xenvials[ixv] != '') {
if (endelim == ',"') {
pvials.push(xenvials[eval(1 + ixv)].split('"')[0]);
if (xenvials[ixv].indexOf('",') != -1) { xenvials[ixv]=xenvials[ixv].replace(xenvials[ixv].split('",')[0] + '",',''); }
minicom=xenvials[ixv].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (endelim == '",') {
pvials.push(xenvials[ixv].split('"')[0]);
if (xenvials[eval(1 + ixv)].indexOf(',"') != -1) { xenvials[eval(1 + ixv)]=xenvials[eval(1 + ixv)].replace(',"' + xenvials[eval(1 + ixv)].split(',"')[0],''); }
minicom=xenvials[eval(1 + ixv)].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (('' + xenvials[ixv]).trim() != '' && ('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '') {
//alert('envials.push(' + xenvials[ixv] + ');');
envials.push(xenvials[ixv]);
} else if (('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != pyoullneverfindthis) {
//alert('pvials.push(' + xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"') + ')');
pvials.push(xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"'));
if (pfirst) {
pfirst=false;
pyoullneverfindthis='youllnever_find_this';
}
} else {
//alert('envials.push(' + xenvials[ixv] + ')');
envials.push(xenvials[ixv]);
}
pfirst=false;
}
}
}

… as exemplified by …

Originally 327500,672500,”Arthur’s Seat, (Fort)”
Out of the PHP <html><body onload=”parent.document.getElementById(‘ifcsv’).srcdoc = ‘<pre>327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)<br></pre>';”></body></html>
Via Parent Iframe body innerHTML 327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)
window.localStorage 327500,672500,Arthur’s Seat&comma; (Fort)
Finally
E N Placename
327500 672500 Arthur’s Seat, (Fort)

And we’d like to thank this great link for today’s tutorial’s testing CSV data as per egp.csv


327500,672500,"Arthur's Seat, (Fort)"
316500,662500,"Bavelaw Castle"
322500,677500,"Caroline Park"
316500,672500,"Castle Gogar"
314500,674500,"Cat Stane"
323500,670500,"Craig Ho"
321500,674500,"Craigcrook Castle"
328500,670500,"Craigmillar Castle"

… in our changed “sister” PHP SurveyTraverse.php code called by our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS Survey Traverse Canvas Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

Onto yesterday’s HTML and Javascript and CSS NSW State Survey Traverse Tutorial progress with our Survey Traverse web application functionality we wanted to augment …

  • the existent tabular data … with …
  • new canvas graphics to show the (Easting,Northing) co-ordinate sets of the Survey Traverse

… involving the collection of minimums and maximums Javascript “ifzeromakezero” function code changes …


var edone=false, ndone=false;
var maxe=-1.0, mine=-1.0, maxn=-1.0, minn=-1.0;


function ifzeromakezero(innum,e_or_n) {
var cinnum = innum.toString();
if (cinnum.indexOf("e-") != (0 - 1)) {
if (e_or_n == 1) {
if (!edone) {
mine=0.0;
maxe=0.0;
} else {
if (mine > 0.0) { mine=0.0; }
if (maxe < 0.0) { maxe=0.0; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=0.0; maxn=0.0; } else { if (minn > 0.0) { minn=0.0; }
if (maxn < 0.0) { maxn=0.0; } } ndone=true; }

return 0.000;
}
if (e_or_n == 1) {
if (!edone) {
mine=innum;
maxe=innum;
} else {
if (mine > innum) { mine=innum; }
if (maxe < innum) { maxe=innum; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=innum; maxn=innum; } else { if (minn > innum) { minn=innum; }
if (maxn < innum) { maxn=innum; } } ndone=true; }

return innum;
}

… and the canvas creation and line plotting, featuring (thanks to (linear gradients on canvas) ideas from this excellent link) canvas Javascript code …


document.getElementById('overlays').innerHTML+='<br><br><canvas style="background-color:#f0f0f0;border:2px dashed red;" height=' + eval(40 + eval('' + maxn) - eval('' + minn)) + ' width=' + eval(40 + eval('' + maxe) - eval('' + mine)) + ' id=mycanvas></canvas>';
setTimeout(postspanscheck, 5000);
var ele=document.getElementById('mycanvas');
var context=document.getElementById('mycanvas').getContext('2d');
var iz=0, mto=true, grad;

// var pts = [[0, 0, "red"], [0, 0, "green"], [0, 0, "blue"], [0, 0, "purple"], [0, 0, "olive"], [0, 0, "magenta"], [0, 0, "cyan"], [0, 0, "brown"], [0, 0, "black"], [0, 0, "pink"], [0, 0, "darkgreen"], [0, 0, "darkblue"], [0, 0, "darkorange"]];
var pts = [[0, 0, "red"], [0, 0, "orange"], [0, 0, "yellow"], [0, 0, "green"], [0, 0, "cyan"], [0, 0, "blue"], [0, 0, "violet"]];
var begin = pts[0];
var end = pts[1];

while (document.getElementById('E' + iz)) {
if (document.getElementById('E' + iz).value != '') {
if (mto) {
context.lineWidth = 6;
context.lineJoin = "round";
context.lineCap = "round";
//context.strokeStyle = "black";
context.beginPath();
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
} else {
end=pts[eval(1 + eval(iz % 5))];
end[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
end[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
grad = context.createLinearGradient(begin[0], begin[1], end[0], end[1]);
grad.addColorStop(0, begin[2]);
grad.addColorStop(1, end[2]);
context.strokeStyle = grad;
context.lineTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
context.stroke();
//context.strokeStyle = "black";
context.beginPath();
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
}
mto=false;
}
iz++;
}
}

… via our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS NSW State Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS NSW State Survey Traverse Co-ordinates Tutorial

HTML and Javascript and CSS NSW State Survey Traverse Tutorial

Yesterday’s HTML and Javascript and CSS Survey Traverse Co-ordinates Tutorial was kind of “mathematical” by nature. Today we add some realism.

This realism stems from the discovery of a NSW State Survey mark in the local area (to the right of today’s tutorial picture). Having a Land Surveying background, an indestructible looking survey mark is a joy to behold. The thing is though, when I was doing a Bachelor Of Surveying in the late 1970’s and early 1980’s, this survey mark was much more an object of awe than perhaps such a mark is to people, even me, today. Mystery surrounded it, it taking a visit to a government agency (NSW Titles Office), and no doubt some paperwork to match, would be required to find out anything about it, Land Surveyors at the very least curious about …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (in whatever ellipsoid of relevance)
  • Reduced Level (at whatever datum of relevance)

We decided on our iPhone to feed that SS46391 survey mark name into Google, thanks, and see what comes up, and discovered the “NSW Survey Marks” iOS app that we downloaded and spent a happy half hour “in a wooooorrrrrllllllddd of discovery and interest” (well, you had to be there).

You see, this app is just great! The information above is augmented by location Sketch Maps (that a Land Surveyor from the past would have created in the NSW Titles Office).

This way, in that half hour we looked for 3 survey marks in that local area, and gleaned their co-ordinates to come up with the …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (from the NSW Survey Marks app)
  • Bearings and Distances and theodolite Angles derived

… also shown in today’s tutorial picture … via our changed SurveyTraverse.html live run link, the changes concerning allowing both …

  • decimal degrees … as well as …
  • degrees, minutes and seconds (useful for setting an angle with a theodolite)

… for those aforesaid mentioned Angles and Bearings (with your compass or iPhone compass app).

Some of this “NSW Survey Marks” app’s workings can be viewed with today’s accompanying PDF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

Here is a tutorial showing some client-side basics in HTML and Javascript and CSS all in the one HTML file, to simplify concepts. The tutorial subject matter is a webpage to perform Survey Traverse calculations. A Survey Traverse is:

Traverse is a method in the field of surveying to establish control networks.[1] It is also used in geodesy. Traverse networks involve placing survey stations along a line or path of travel, and then using the previously surveyed points as a base for observing the next point. Traverse networks have many advantages, including:

Less reconnaissance and organization needed;
While in other systems, which may require the survey to be performed along a rigid polygon shape, the traverse can change to any shape and thus can accommodate a great deal of different terrains;
Only a few observations need to be taken at each station, whereas in other survey networks a great deal of angular and linear observations need to be made and considered;
Traverse networks are free of the strength of figure considerations that happen in triangular systems;
Scale error does not add up as the traverse is performed. Azimuth swing errors can also be reduced by increasing the distance between stations.

The traverse is more accurate than triangulateration[2] (a combined function of the triangulation and trilateration practice).[3]

Let’s see some simple HTML in action in a tutorial …

Link to HTML “spiritual home” … at W3Schools has many tutorials.
Link to Survey Traverse live run … here.
Link to Survey Traverse live run (additional Google Line Chart functionality) here.
Link to Survey Traverse information … from Wikipedia from which quote above comes.
Link to some downloadable HTML code … rename to SurveyTraverse.html which packages up a lot of Javascript and a little bit of CSS … or JaCvasScriptS … not sure whether this would ever catch on.
Link to some downloadable PHP programming code (additional Google Line Chart functionality) … rename to SurveyTraverse.php

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Land Surveying, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Emoji Tutorial

Onto yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial‘s contextual themes we extend those ideas by linking …

… allowing a ([EmojiCodePointList]) delimited suffix to placenames literally “spelling out” the CodePoint necessary to define the emoji, an example [EmojiCodePointList] (for Surfers Paradise) being …


Surfers Paradise (onetwosevenninefiveeightdotsixfivezerothreenine)

… ie. 🏖️ is &#127958;&#65039;

Recognizing such a ([EmojiCodePointList]) it is stripped from the web application’s understanding of what that placename is, after having made the Emoji definition changes, as defined by the user.

A further retweaked geo_chart.php Geo Chart interfacer (as called by unchanged “last changed” SurveyTraverse.htm) Geo Chart calling live run link with an improved Emoji context, is, again, worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Context Tutorial

We thought to improve on yesterday’s HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial conjoining of …

… it’s good to be able to use …

  • Emojis
  • Link Lines

… but the Link Lines, then, had limited “context”. But what if the Survey Traverse had a …

  • xx-large start point Emoji
  • x-large end point Emoji

? Yes, as you can read at this useful link the CSS for font-size has some useful and interesting settings we’d like to link into our Google Chart Geo Chart SVG text newly added “class”, as required …


function emojimaybe(jnentity, jnentwo, endtag) {
var jjj;
var xclass='';
var allnum=true, iu;
var inentity=jnentity;
var inentwo=jnentwo;
var classesare=['border','bcoly','cglow','glow','xxsmall','xsmall','xx-small','x-small','smaller','small','xxlarge','xlarge','xx-large','x-large','larger','large','tenp','twentyp','onefiftyp','fiftyp','twohundredp','threehundredp','fourhundredp','fivehundredp','sixhundredp'];

if (inentwo != '') {
if (inentwo.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentwo=inentwo.replace(inentwo.replace(/\_/g,' ').split(' ')[0], inentwo.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('Xclass=' + xclass);
for (iu=0; iu<inentwo.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentwo.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentwo.indexOf('_') != -1) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentwo.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
allnum=true;
xclass='';
if (inentity != '') {
if (inentity.replace(/\_/g,' ').substring(0,1) != ' ') {
for (jjj=0; jjj<classesare.length; jjj++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].indexOf(classesare[jjj]) != -1) {
if (xclass != '') {
xclass=xclass.replace('\"' + \"'\", '' + classesare[jjj].replace('-','') + '\"' + \"'\");
} else {
xclass=' class=\"' + classesare[jjj].replace('-','') + '\"';
}
inentity=inentity.replace(inentity.replace(/\_/g,' ').split(' ')[0], inentity.replace(/\_/g,' ').split(' ')[0].replace(classesare[jjj],''));
}
}
//alert('xclass=' + xclass);
for (iu=0; iu<inentity.replace(/\_/g,' ').split(' ')[0].length; iu++) {
if (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) != '.' && (inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) < '0' || inentity.replace(/\_/g,' ').split(' ')[0].substring(iu,eval(1 + iu)) > '9')) {
allnum=false;
}
}
if (allnum && inentity.indexOf('_') != -1) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
if (allnum) return xclass + '>&#' + inentity.replace(/\_/g,' ').split(' ')[0].replace(/\./g,';&#') + ';</text>';
}
}
return endtag;
}

A retweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link with an improved context, is worth a look.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

HTML and Javascript and CSS Survey Traverse CSV Geo Chart Tutorial

The recent HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial had us catering for decimal latitude and longitude input data. Within the logic for this we could be using …

… the latter choice made when the distances involved in the Survey Traverse are large. That Geo Chart is both capable of being worked to show …

  • Emojis
  • Link Lines

… an offer too good to refuse, and you can read about at Google Geo Chart Co-ordinate Emojis Tutorial. Except, that is, if in the meantime, our inhouse Geo Chart interfacing PHP logic does not keep up with Google changes to the Geo Chart itself. And that sad scenario was our discovery then, and today we fix it up.

With any data scraping feeling third-party feeling logic that we need to do here, it is “the data” that is everything, and you’re first troubleshooting question should be …

Some thing that used to work no longer works. What has changed with the underlying data?

Our strategy here was to capture the outerHTML (ie. element contents) of geo_chart.php’s “chart_div” (div) element of a scenario that should involve emojis and/or link lines for a …

  • now scenario (which is easy via a Web Inspector -> Console -> point at “chart_div” -> two finger gesture Copy OuterHTML) … versus …
  • then scenario (which we scraped together scouring snippets of data from the past existing on this MacBook Pro) of a similar scenario

… and a few prudent carriage returns revealed to us the issue. We had assumed a first HTML defs element with ID “defs” but that was no longer the case, that change cutting off a whole lot of (PHP written out) Javascript logic making Emojis and Link Lines work with Geo Charts (given savvy user usage).

A tweaked geo_chart.php Geo Chart interfacer called by our changed SurveyTraverse.htm Geo Chart calling live run link, the work leading to this more obvious after viewing today’s animated GIF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

HTML and Javascript and CSS Survey Traverse CSV Placename Tutorial

You might say the progress made in yesterday’s HTML and Javascript and CSS Survey Traverse CSV Co-ordinates Tutorial was …

  • inordinately complex … for …
  • not enough “gain”

… two criticisms we can live with, and today, we “eat into” the credibility of, on two fronts …

  1. we extend functionality, to include “placename” data … and …

  2. that very complexity is not all bad news, as the involvement of PHP and HTML data format is also “an opportunity” to arrange data (and delimitation) to our own programming arrangements

It is “an opportunity” to come out of the PHP with two numeric fields and up to one (ie. optional placename) string field for each <br> delimited HTML record (that <br> allowing for a one Javascript codeline achieving this (though this aspect is not new to today’s work)).

It is “an opportunity” to not involve string delimitation coming out of the PHP on its way to the parent HTML iframe via its “srcdoc” attribute. How can we arrange this? Well, helped out by the usefulness of this great link we constructed the PHP function …

<?php

function clean_csv_commas($csv, $indelimis) { // thanks to https://stackoverflow.com/questions/10739016/how-to-remove-commas-between-double-quotes-in-php
$until=true;
$qdelim = '"';
$bqdelim = "'";
$altbqdelim = "&apos;";
$comma = ',';
$altcomma = '&comma;';
$altqdelim = '&quot;';
$prevcomma=FALSE;
$aftcomma=FALSE;
if ($indelimis == "'") {
$qdelim=$indelimis;
$bqdelim='"';
$altqdelim = '&apos;';
$altbqdelim = '&quot;';
}
$len = strlen($csv);
$inside_block = FALSE;
$out='';
$rep='';
for ($i=0; $i<$len; $i++) {
if (ord($csv[$i]) < 32) {
$inside_block=FALSE;
$until=false;
} else if ($csv[$i] == $qdelim) {
if ($i == 0) {
$prevcomma=FALSE;
$inside_block=TRUE;
} else if (($i + 1) == $len) {
$aftcomma=FALSE;
$inside_block=FALSE;
} else {
if ($csv[-1 + $i] == ',' || ord($csv[-1 + $i]) < 32) { $prevcomma=TRUE; } else { $prevcomma=FALSE; }
if ($csv[1 + $i] == ',' || ord($csv[1 + $i]) < 32) { $aftcomma=TRUE; } else { $aftcomma=FALSE; }
if ($inside_block) {
if ($aftcomma) { $inside_block=FALSE; }
} else {
if ($prevcomma) { $inside_block=TRUE; }
}
}
}

//if ($until) {
// $rep.="\n" . $csv[$i] . " \$inside_block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
//}
if ($csv[$i] == $comma && $inside_block) {
if ($until) {
$rep.="\n" . $csv[$i] . " \$inside-block=" . $inside_block . " \$prevcomma=" . $prevcomma . " \$aftcomma=" . $aftcomma;
}
$out.=$altcomma;
} else if ($csv[$i] == $qdelim && $inside_block && !$aftcomma && !$prevcomma) {
$out.=$altqdelim;
} else if ($csv[$i] == $bqdelim && $inside_block) {
$out.=$altbqdelim;
} else {
$out.=$csv[$i];
}

}
if ($indelimis == "") {
//file_put_contents("zerocsv.xxx", $csv);
//file_put_contents("one_csv.xxx", $rep);
//file_put_contents("onecsv.xxx", $out);
$out=str_replace("'","",str_replace('"','',clean_csv_commas($out, "'")));
//file_put_contents("twocsv.xxx", $out);
}
return $out;
}

?>

… called in this way

<?php

if (isset($_GET['csvfile'])) {
$fname=str_replace("+"," ",urldecode($_GET['csvfile']));
$csvcont='';
if (strpos(strtolower($fname),"http") !== false) {
$csvcont=file_get_contents($fname);
} else if (file_exists($fname)) {
$csvcont=file_get_contents($fname);
}
//file_put_contents("threecsv.xxx", '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>');
echo '<html><body onload="parent.document.getElementById(' . "'" . ifcsv . "'" . ').srcdoc=' . "'<pre>" . str_replace("\r","<br>",str_replace("\n","<br>",str_replace("\r\n","<br>",str_replace("'","",clean_csv_commas($csvcont,""))))) . "</pre>'" . ';"></body></html>';
exit;
}

?>

… to replace any need for string delimitation (via ‘ or ” characters encasing any commas mapped to &comma; or fellow string delimiters to &quot; or &apos; respectively) with HTML Entity use …


var eoff=0.0;
var noff=0.0;
var envials=[];
var pvials=[];
if (window.localStorage) {
// 34,56,78,45 ... ,
// 34,56,"One",78,45,"Two" ... ,"
// "One",34,56,"Two",78,45 ... ",
var acontt=decodeURIComponent(('' + localStorage.getItem('en_st')).replace(/^null$/g,'')).replace(/\+/g,' ');
if (acontt != '') { localStorage.removeItem('en_st'); }
//alert(acontt);
var minicom=[];
var endelim=',';
if (acontt.indexOf(',"') != -1 && acontt.indexOf('",') != -1) {
if (eval('' + acontt.indexOf('",')) < eval('' + acontt.indexOf(',"'))) {
endelim='",';
} else {
endelim=',"';
}
} else if (acontt.indexOf(',"') != -1) {
endelim=',"';
} else if (acontt.indexOf('",') != -1) {
endelim='",';
}
var pfirst=true;
var pyoullneverfindthis='';
var jxv=0;
var xenvials=acontt.split(endelim);
xenvials.push('');
for (var ixv=0; ixv<xenvials.length; ixv++) {
if (xenvials[ixv] != '') {
if (endelim == ',"') {
pvials.push(xenvials[eval(1 + ixv)].split('"')[0]);
if (xenvials[ixv].indexOf('",') != -1) { xenvials[ixv]=xenvials[ixv].replace(xenvials[ixv].split('",')[0] + '",',''); }
minicom=xenvials[ixv].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (endelim == '",') {
pvials.push(xenvials[ixv].split('"')[0]);
if (xenvials[eval(1 + ixv)].indexOf(',"') != -1) { xenvials[eval(1 + ixv)]=xenvials[eval(1 + ixv)].replace(',"' + xenvials[eval(1 + ixv)].split(',"')[0],''); }
minicom=xenvials[eval(1 + ixv)].split(',');
for (jxv=0; jxv<minicom.length; jxv++) {
envials.push(minicom[jxv]);
}
} else if (('' + xenvials[ixv]).trim() != '' && ('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '') {
//alert('envials.push(' + xenvials[ixv] + ');');
envials.push(xenvials[ixv]);
} else if (('' + xenvials[ixv]).replace(/\ /g,'').replace(/\-/g,'').replace(/\./g,'').replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != pyoullneverfindthis) {
//alert('pvials.push(' + xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"') + ')');
pvials.push(xenvials[ixv].replace(/\&amp\;/g,"&").replace(/\&apos\;/g,"'").replace(/\&quot\;/g,'"'));
if (pfirst) {
pfirst=false;
pyoullneverfindthis='youllnever_find_this';
}
} else {
//alert('envials.push(' + xenvials[ixv] + ')');
envials.push(xenvials[ixv]);
}
pfirst=false;
}
}
}

… as exemplified by …

Originally 327500,672500,”Arthur’s Seat, (Fort)”
Out of the PHP <html><body onload=”parent.document.getElementById(‘ifcsv’).srcdoc = ‘<pre>327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)<br></pre>';”></body></html>
Via Parent Iframe body innerHTML 327500,672500,Arthur&amp;apos;s Seat&amp;comma; (Fort)
window.localStorage 327500,672500,Arthur’s Seat&comma; (Fort)
Finally
E N Placename
327500 672500 Arthur’s Seat, (Fort)

And we’d like to thank this great link for today’s tutorial’s testing CSV data as per egp.csv


327500,672500,"Arthur's Seat, (Fort)"
316500,662500,"Bavelaw Castle"
322500,677500,"Caroline Park"
316500,672500,"Castle Gogar"
314500,674500,"Cat Stane"
323500,670500,"Craig Ho"
321500,674500,"Craigcrook Castle"
328500,670500,"Craigmillar Castle"

… in our changed “sister” PHP SurveyTraverse.php code called by our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS Survey Traverse Canvas Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

HTML and Javascript and CSS Survey Traverse Canvas Tutorial

Onto yesterday’s HTML and Javascript and CSS NSW State Survey Traverse Tutorial progress with our Survey Traverse web application functionality we wanted to augment …

  • the existent tabular data … with …
  • new canvas graphics to show the (Easting,Northing) co-ordinate sets of the Survey Traverse

… involving the collection of minimums and maximums Javascript “ifzeromakezero” function code changes …


var edone=false, ndone=false;
var maxe=-1.0, mine=-1.0, maxn=-1.0, minn=-1.0;


function ifzeromakezero(innum,e_or_n) {
var cinnum = innum.toString();
if (cinnum.indexOf("e-") != (0 - 1)) {
if (e_or_n == 1) {
if (!edone) {
mine=0.0;
maxe=0.0;
} else {
if (mine > 0.0) { mine=0.0; }
if (maxe < 0.0) { maxe=0.0; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=0.0; maxn=0.0; } else { if (minn > 0.0) { minn=0.0; }
if (maxn < 0.0) { maxn=0.0; } } ndone=true; }

return 0.000;
}
if (e_or_n == 1) {
if (!edone) {
mine=innum;
maxe=innum;
} else {
if (mine > innum) { mine=innum; }
if (maxe < innum) { maxe=innum; } } edone=true; } else if (e_or_n == 2) { if (!ndone) { minn=innum; maxn=innum; } else { if (minn > innum) { minn=innum; }
if (maxn < innum) { maxn=innum; } } ndone=true; }

return innum;
}

… and the canvas creation and line plotting, featuring (thanks to (linear gradients on canvas) ideas from this excellent link) canvas Javascript code …


document.getElementById('overlays').innerHTML+='<br><br><canvas style="background-color:#f0f0f0;border:2px dashed red;" height=' + eval(40 + eval('' + maxn) - eval('' + minn)) + ' width=' + eval(40 + eval('' + maxe) - eval('' + mine)) + ' id=mycanvas></canvas>';
setTimeout(postspanscheck, 5000);
var ele=document.getElementById('mycanvas');
var context=document.getElementById('mycanvas').getContext('2d');
var iz=0, mto=true, grad;

// var pts = [[0, 0, "red"], [0, 0, "green"], [0, 0, "blue"], [0, 0, "purple"], [0, 0, "olive"], [0, 0, "magenta"], [0, 0, "cyan"], [0, 0, "brown"], [0, 0, "black"], [0, 0, "pink"], [0, 0, "darkgreen"], [0, 0, "darkblue"], [0, 0, "darkorange"]];
var pts = [[0, 0, "red"], [0, 0, "orange"], [0, 0, "yellow"], [0, 0, "green"], [0, 0, "cyan"], [0, 0, "blue"], [0, 0, "violet"]];
var begin = pts[0];
var end = pts[1];

while (document.getElementById('E' + iz)) {
if (document.getElementById('E' + iz).value != '') {
if (mto) {
context.lineWidth = 6;
context.lineJoin = "round";
context.lineCap = "round";
//context.strokeStyle = "black";
context.beginPath();
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
} else {
end=pts[eval(1 + eval(iz % 5))];
end[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
end[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
grad = context.createLinearGradient(begin[0], begin[1], end[0], end[1]);
grad.addColorStop(0, begin[2]);
grad.addColorStop(1, end[2]);
context.strokeStyle = grad;
context.lineTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
context.stroke();
//context.strokeStyle = "black";
context.beginPath();
context.moveTo(eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine)), eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn)));
begin=pts[eval(iz % pts.length)];
begin[0] = eval(20 + eval('' + document.getElementById('E' + iz).value) - eval('' + mine));
begin[1] = eval(eval('' + maxn) + 20 - eval('' + document.getElementById('N' + iz).value) + 0 * eval('' + minn));
}
mto=false;
}
iz++;
}
}

… via our changed SurveyTraverse.htm live run link.


Previous relevant HTML and Javascript and CSS NSW State Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS NSW State Survey Traverse Co-ordinates Tutorial

HTML and Javascript and CSS NSW State Survey Traverse Tutorial

Yesterday’s HTML and Javascript and CSS Survey Traverse Co-ordinates Tutorial was kind of “mathematical” by nature. Today we add some realism.

This realism stems from the discovery of a NSW State Survey mark in the local area (to the right of today’s tutorial picture). Having a Land Surveying background, an indestructible looking survey mark is a joy to behold. The thing is though, when I was doing a Bachelor Of Surveying in the late 1970’s and early 1980’s, this survey mark was much more an object of awe than perhaps such a mark is to people, even me, today. Mystery surrounded it, it taking a visit to a government agency (NSW Titles Office), and no doubt some paperwork to match, would be required to find out anything about it, Land Surveyors at the very least curious about …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (in whatever ellipsoid of relevance)
  • Reduced Level (at whatever datum of relevance)

We decided on our iPhone to feed that SS46391 survey mark name into Google, thanks, and see what comes up, and discovered the “NSW Survey Marks” iOS app that we downloaded and spent a happy half hour “in a wooooorrrrrllllllddd of discovery and interest” (well, you had to be there).

You see, this app is just great! The information above is augmented by location Sketch Maps (that a Land Surveyor from the past would have created in the NSW Titles Office).

This way, in that half hour we looked for 3 survey marks in that local area, and gleaned their co-ordinates to come up with the …

  • (Easting, Northing) co-ordinates in AMG (Australian Map Grid) (from the NSW Survey Marks app)
  • Bearings and Distances and theodolite Angles derived

… also shown in today’s tutorial picture … via our changed SurveyTraverse.html live run link, the changes concerning allowing both …

  • decimal degrees … as well as …
  • degrees, minutes and seconds (useful for setting an angle with a theodolite)

… for those aforesaid mentioned Angles and Bearings (with your compass or iPhone compass app).

Some of this “NSW Survey Marks” app’s workings can be viewed with today’s accompanying PDF presentation.


Previous relevant HTML and Javascript and CSS Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

Here is a tutorial showing some client-side basics in HTML and Javascript and CSS all in the one HTML file, to simplify concepts. The tutorial subject matter is a webpage to perform Survey Traverse calculations. A Survey Traverse is:

Traverse is a method in the field of surveying to establish control networks.[1] It is also used in geodesy. Traverse networks involve placing survey stations along a line or path of travel, and then using the previously surveyed points as a base for observing the next point. Traverse networks have many advantages, including:

Less reconnaissance and organization needed;
While in other systems, which may require the survey to be performed along a rigid polygon shape, the traverse can change to any shape and thus can accommodate a great deal of different terrains;
Only a few observations need to be taken at each station, whereas in other survey networks a great deal of angular and linear observations need to be made and considered;
Traverse networks are free of the strength of figure considerations that happen in triangular systems;
Scale error does not add up as the traverse is performed. Azimuth swing errors can also be reduced by increasing the distance between stations.

The traverse is more accurate than triangulateration[2] (a combined function of the triangulation and trilateration practice).[3]

Let’s see some simple HTML in action in a tutorial …

Link to HTML “spiritual home” … at W3Schools has many tutorials.
Link to Survey Traverse live run … here.
Link to Survey Traverse live run (additional Google Line Chart functionality) here.
Link to Survey Traverse information … from Wikipedia from which quote above comes.
Link to some downloadable HTML code … rename to SurveyTraverse.html which packages up a lot of Javascript and a little bit of CSS … or JaCvasScriptS … not sure whether this would ever catch on.
Link to some downloadable PHP programming code (additional Google Line Chart functionality) … rename to SurveyTraverse.php

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment