Intermission

Been a bit of a while since my last post – many things have been happening to keep me otherwise occupied, not least that I’ve had to quit my flat in the Cross for apparent rennovations, and put all my stuff in store, including my PC, Pi’s/cameras and 3D TV.

Currently residing at a backpackers just over the road until I can get somewhere new sorted out. In the meantime here’s a quick peek of a somewhat rough video from the hard drive of my work laptop – it’ll need to be edited and run through stabilisation plugins etc. More posts when things are a bit more settled. They could hardly be less…

https://davegorst.org/wp-content/uploads/2015/01/skyline2.zip

Release early/release often/release terrible

The code for stitching together 3D images from left/right pairs is up on Google Code (https://code.google.com/p/tools23d/). Looking through it I can see about 80 things that are a mite shonky (not least that the wraparound code isn’t done yet), but it’s sort of my mid-year resolution to actually release stuff rather than tinker for a decade and a day. It’s standard ANSI C/C89 if you fancy compiling it up.

Yes – it would have been here a sight quicker using yer standard C++/Boost type malarkey, but I did it in bog-standard C basically because a) I wanted to check I could still write non-objecty code and hadn’t permanently sprained my brain, and b) when I started writing it when I only had a Raspberry Pi as a development machine and the compile times were eating away at my sanity.

Currently still faffing with the Pi/Arduino side, -will bung that up too soon-ish once I’m sure I’ve got both camera’s synced properly …

Emscriptening

Hmm – so once I’ve got the timelapse/SDL2/3D stuff out of the way I’m looking to kick off another project – investigating adding a VXML backend to Emscripten (a source-to-source compiler built on top of LLVM). This should give us the following advantages :

  • Retargetability
  • Lower skills barrier
  • Built-in optimisation

It’ll probably be a personal project (unless I can get anyone to pay me for it of course …). Have set up a Google Code project for the photo-to-3D code – will upload once I’ve got a few more kinks knocked out of it (“release early and release often” and all that). I’m trying not run afoul of the usual twin tag team of perfectionism and explosive feature-creep, but it’s difficult – even on such a small project.

Migraine simulator

I’ve just returned from attempting to do some more Raspberry Pi timelapse filming with 2 camera’s on the way  home from work – I think a drop of rain scored a direct hit on the left camera because it’s all gone a mite Forbidden Planet :

I’ll put up some videos in half SBS 3D suitable for a 3d TV when I’ve got some more material and finished the relevant code.

Things going on behind my back

This is the view from my window at work. I actually have a working PC now, hence I could edit this in Openshot, rather than rely on ffmpeg from the commandline.

EDIT : Here’s the original definition version (minus a bit of footage), if anyone is interested :

https://davegorst.org/wp-content/uploads/2014/09/cranes.zip

You’ll need to unzip, as WordPress doesn’t allow me to upload Matroska or .m4v without conversion.

Reading SVG paths using Boost

Here’s a bit of code to read SVG paths – it’s from my code to convert vector graphics to OpenVG commands and 6809 assembler for the Vectrex (among other things). However, as that’s progressing at around the speed of continental drift I may as well put it up here in the hope that someone else may get some use out of it. It uses Boost.Spirit, which is an excellent method of turning EBNF grammars into something that looks like Martian hieroglyphics, should you be so minded :

// Literals.</pre>
<pre>
nsParser::rule<sIter> flag;
nsParser::rule<sIter> comma;
nsParser::rule<sIter> sign;
nsParser::rule<sIter> wsp;
nsParser::rule<sIter> digit;
nsParser::rule<sIter> dot;
nsParser::rule<sIter> comma_wsp;

nsParser::rule<sIter> exponent;
nsParser::rule<sIter> digit_sequence;
nsParser::rule<sIter> integer_constant;
nsParser::rule<sIter> floating_point_constant;
nsParser::rule<sIter> fractional_constant;

nsParser::rule<sIter> number;
nsParser::rule<sIter> nonnegative_number;
nsParser::rule<sIter> coordinate;
nsParser::rule<sIter> coordinate_pair;

// Path commands.

nsParser::rule<sIter> closepath;

nsParser::rule<sIter> lineto_argument_sequence;
nsParser::rule<sIter> lineto;
nsParser::rule<sIter> moveto_argument_sequence;
nsParser::rule<sIter> moveto;

nsParser::rule<sIter> horizontal_lineto_argument_sequence;
nsParser::rule<sIter> horizontal_lineto;
nsParser::rule<sIter> vertical_lineto_argument_sequence;
nsParser::rule<sIter> vertical_lineto;

nsParser::rule<sIter> curveto;
nsParser::rule<sIter> curveto_argument;
nsParser::rule<sIter> curveto_argument_sequence;

nsParser::rule<sIter> smooth_curveto;
nsParser::rule<sIter> smooth_curveto_argument;
nsParser::rule<sIter> smooth_curveto_argument_sequence;

nsParser::rule<sIter> quadratic_bezier_curveto;
nsParser::rule<sIter> quadratic_bezier_curveto_argument;
nsParser::rule<sIter> quadratic_bezier_curveto_argument_sequence;

nsParser::rule<sIter> smooth_quadratic_bezier_curveto;
nsParser::rule<sIter> smooth_quadratic_bezier_curveto_argument;
nsParser::rule<sIter> smooth_quadratic_bezier_curveto_argument_sequence;

nsParser::rule<sIter> elliptical_arc;
nsParser::rule<sIter> elliptical_arc_argument;
nsParser::rule<sIter> elliptical_arc_argument_sequence;

nsParser::rule<sIter> drawto_command;
nsParser::rule<sIter> drawto_commands;
nsParser::rule<sIter> moveto_drawto_command_group;
nsParser::rule<sIter> moveto_drawto_command_groups;
nsParser::rule<sIter> svg_path;

CParsePath::CParsePath ()
{
    InputString = "";
    itStart = InputString.begin ();
    itEnd = InputString.end ();

    // Define parser elements.

    flag = (nsParser::lit ('0') | nsParser::lit ('1'));
    comma = (nsParser::lit (','));
    sign = (nsParser::lit ('+') | nsParser::lit ('-'));

    wsp = (
        nsParser::lit (' ') |
        nsParser::lit ('\t') |
        nsParser::lit ('\r') |
        nsParser::lit ('\n')
    );

    digit = (
        nsParser::lit ('0') |
        nsParser::lit ('1') |
        nsParser::lit ('2') |
        nsParser::lit ('3') |
        nsParser::lit ('4') |
        nsParser::lit ('5') |
        nsParser::lit ('6') |
        nsParser::lit ('7') |
        nsParser::lit ('8') |
        nsParser::lit ('9')
    );

    dot = nsParser::lit ('.');



// 0 or 1 : EBNF ? Qi -
// 0 or more : EBNF * Qi *
// 1 or more : EBNF + Qi +

    comma_wsp = (+wsp >> -comma >> *wsp) | (comma >> *wsp);
/*
digit-sequence:
    digit
    | digit digit-sequence

    NOTE : Don't understand - isn't this just "one or more"?
*/

    digit_sequence = (+digit);
    exponent = ((nsParser::lit ('E') | nsParser::lit ('e')) >> -sign >> digit_sequence);
    integer_constant = digit_sequence;
    fractional_constant = ((-digit_sequence >> dot >> digit_sequence) | (digit_sequence >> dot));
    floating_point_constant = ((fractional_constant >> -digit_sequence) | (digit_sequence >> exponent));
    number = ((-sign >> integer_constant) | (-sign >> floating_point_constant));
    nonnegative_number = (integer_constant | floating_point_constant);
    coordinate = number;
    coordinate_pair = (coordinate >> -comma-wsp >> coordinate);

    closepath = (nsParser::lit (ABSOLUTE_CLOSEPATH) | nsParser::lit (RELATIVE_CLOSEPATH));
    lineto_argument_sequence = ((coordinate_pair) | (coordinate_pair >> -comma_wsp >> lineto_argument_sequence));
    lineto = (nsParser::lit (ABSOLUTE_LINETO) | nsParser::lit (RELATIVE_LINETO)) >> *wsp >> lineto_argument_sequence;
    moveto_argument_sequence = ((coordinate_pair) | (coordinate_pair >> -comma_wsp >> lineto_argument_sequence));
    moveto = (nsParser::lit (ABSOLUTE_MOVETO) | nsParser::lit (RELATIVE_MOVETO)) >> *wsp >> moveto_argument_sequence;
    horizontal_lineto_argument_sequence = ((coordinate) | (coordinate >> -comma_wsp >> horizontal_lineto_argument_sequence));
    horizontal_lineto = (nsParser::lit (ABSOLUTE_HLINETO) | nsParser::lit (RELATIVE_HLINETO)) >> *wsp >> horizontal_lineto_argument_sequence;
    vertical_lineto_argument_sequence = ((coordinate) | (coordinate >> -comma_wsp >> vertical_lineto_argument_sequence));
    vertical_lineto = (nsParser::lit (ABSOLUTE_VLINETO) | nsParser::lit (RELATIVE_VLINETO)) >> *wsp >> vertical_lineto_argument_sequence;
    curveto_argument = (coordinate_pair >> -comma_wsp >> coordinate_pair >> -comma_wsp >> coordinate_pair);
    curveto_argument_sequence = ((curveto_argument) | (curveto_argument >> -comma-wsp >> curveto_argument_sequence));
    curveto = ((nsParser::lit (ABSOLUTE_CURVETO) | nsParser::lit (RELATIVE_CURVETO)) >> *wsp >> curveto_argument_sequence);
    smooth_curveto_argument = (coordinate_pair >> -comma_wsp >> coordinate_pair >> -comma_wsp >> coordinate_pair);
    smooth_curveto_argument_sequence = ((smooth_curveto_argument) | (smooth_curveto_argument >> -comma-wsp >> smooth_curveto_argument_sequence));
    smooth_curveto = ((nsParser::lit (ABSOLUTE_SCURVETO) | nsParser::lit (RELATIVE_CURVETO)) >> *wsp >> smooth_curveto_argument_sequence);
    quadratic_bezier_curveto_argument = (coordinate_pair >> -comma_wsp >> coordinate_pair);
    quadratic_bezier_curveto_argument_sequence = ((quadratic_bezier_curveto_argument) | (quadratic_bezier_curveto_argument >> -comma-wsp >> quadratic_bezier_curveto_argument_sequence));
    quadratic_bezier_curveto = ((nsParser::lit (ABSOLUTE_QCURVETO) | nsParser::lit (RELATIVE_QCURVETO)) >> *wsp >> quadratic_bezier_curveto_argument_sequence);
    smooth_quadratic_bezier_curveto_argument_sequence = ((smooth_quadratic_bezier_curveto_argument) | (smooth_quadratic_bezier_curveto_argument >> -comma-wsp >> smooth_quadratic_bezier_curveto_argument_sequence));
    smooth_quadratic_bezier_curveto_argument = (coordinate_pair >> -comma_wsp >> smooth_quadratic_bezier_curveto_argument_sequence);
    smooth_quadratic_bezier_curveto = ((nsParser::lit (ABSOLUTE_SQCURVETO) | nsParser::lit (RELATIVE_SQCURVETO)) >> *wsp >> smooth_quadratic_bezier_curveto_argument_sequence);
    elliptical_arc_argument = nonnegative_number >> -comma_wsp >> nonnegative_number -comma_wsp >> number >> comma_wsp >> flag >> comma_wsp >> coordinate_pair;
    elliptical_arc_argument_sequence = (elliptical_arc_argument | (elliptical_arc_argument >> -comma_wsp >> elliptical_arc_argument_sequence));
    elliptical_arc = ((nsParser::lit (ABSOLUTE_ARCTO) | nsParser::lit (RELATIVE_ARCTO)) >> *wsp >> elliptical_arc_argument_sequence);

    drawto_command =
        closepath |
        lineto |
        horizontal_lineto |
        vertical_lineto |
        curveto |
        smooth_curveto |
        quadratic_bezier_curveto |
        smooth_quadratic_bezier_curveto |
        elliptical_arc;

    drawto_commands = (drawto_command | (drawto_command >> *wsp >> drawto_commands));
    moveto_drawto_command_group = (moveto >> *wsp >> -drawto_commands);
    moveto_drawto_command_groups = moveto_drawto_command_group | (moveto_drawto_command_group >> *wsp >> moveto_drawto_command_groups);

    svg_path = *wsp >> -moveto_drawto_command_groups >> *wsp;
}

</pre>
<pre>

NOTE : Obviously this is C++ rather than C, however I can’t seem to get WordPress to accept “C++” as a category name at present …

A fate worse than Canberra

Location location location. Geolocation, in point of fact. I’ve written a quick snippet of code to query http://ipinfo.io for my current latitude and longitude, for the purposes of calculating the times of sunrise and sunset (my Sleepy Pi has now arrived), and it gives some “interesting” results. Whilst running from home is almost creepily accurate, running from work gives me the address of the Canberra office (!), and at the other end of the spectrum running it while tethered via a mobile deposits me here :

Wherezat?
Wherezat?

https://www.google.com.au/maps/@-27,133,104020m/data=!3m1!1e3


#!/usr/bin/python3
# Attempt to determine your position (including latitude and longitude) using your current IP address.
# Unless specified your latitude and longitude will be written to ~/.sunrise/location.ini
# Requires a recent version of Python (preferably 3+).

import urllib.request
import json
from html.parser import HTMLParser, HTMLParseError
import configparser
import os
import argparse
import sys

class CLocationConfig:

    def __init__(self):
        self.config = configparser.ConfigParser ()

    def write(self, section, latitude, longitude):
        home_directory = os.path.expanduser("~")
        write_directory = home_directory+'/.sunrise'
        if not os.path.exists (write_directory):
            os.mkdir (write_directory)
        ini_filename = write_directory+'/location.ini'

        try:
            self.config.read (ini_filename)
        except:
            print ("Error")

        self.config [section] = {}
        self.config [section]['Latitude'] = latitude
        self.config [section]['Longitude'] = longitude

        with open(ini_filename, 'w') as configfile:
            self.config.write(configfile)

class CLocationWeb (HTMLParser) :
    def __init__(self):
        HTMLParser.__init__(self)
        self.JSONData = ""

    def handle_data(self, data):
        self.JSONData = data

    def read(self):
        try:
            response = urllib.request.urlopen('http://ipinfo.io/json')
        except urllib.error.URLError:
            print("URL error connecting to http://ipinfo.io : ",urllib.error.URLError.reason)
        except urllib.error.HTTPError:
            print("HTTP error connecting to http://ipinfo.io (code ",urllib.error.HTTPError.code,")")
        except urllib.error.ContentTooShortError:
            print("Error : Response was too short")

        try:
            self.feed(response.read().decode("utf-8"))
        except HTMLParseError:
            print("Error parsing output \"",HTMLParseError.msg,"\"")
        except:
            print ("Unknown error occurred whilst parsing.")

        if self.JSONData != "":
            location = json.loads(self.JSONData)
        else:
            print("JSON data not set.")
            exit()

        my_latitude, my_longitude = (location['loc'].split(','))

        return my_latitude, my_longitude

def main ():

    LocationWeb = CLocationWeb ()
    LocationConfig = CLocationConfig ()
    parser = argparse.ArgumentParser (prog='geolocate.py')
    parser.add_argument('-s','--section', help='Specify a section name to write in .ini file.',default='Default')
    parser.add_argument('-f', '--filename', help='Write location to this file.',default='~/.sunrise/location.ini')
    args = parser.parse_args()
    location = args.section
    my_latitude, my_longitude = LocationWeb.read ()
    print("Location ", location)
    print("Latitude ", my_latitude)
    print("Longitude ", my_longitude)

    LocationConfig.write(location, my_latitude, my_longitude)

main ()

EDIT : Fixed code tag.