Thursday 4 June 2020

More Star Wars 3D models

I only made R2D2 as a learning excercise, and I'm aware of a lot of mistakes I made with him and I know I could make him better if I tried again...

But, keeping with the star wars theme, I have made a few more models.

I made this tie fighter because I also figured it was be easy.  It is missing some detail, but I'm still happy with the result.

After making the tiefighter, I could not resist the idea of making an x-wing.  I was worried this was a step to far.  But again, happy with the result.


Finally, my latest model is a BB8.  This was one of my first own modeling projects without using blueprints for precision modeling.  Again, he's missing a lot of the detail from the movie shots.  But I'm learning...









Extracting Addresses from FreeText

The Task

A recent task I was set required the extraction of Addresses from Freetext.  Not an easy task, but I was supprised how successful my final result was...  So supprised, that I thought I would share it.

This was a SQL Server based task.  SQL Server's native pattern matching is not sofisticatd enough for the task, so I opted to use Regular Expressions.  I could have used an SSIS package to process to data, but I instead opted to use CLR and a Table-Valued Function to ruturn the found addresses.

I'm not an expert with Regex, I generally have to relearn it everytime I use it, but I often get the pattern and results I want.

Finding addresses

The addresses I needed to find are all UK based, meaning I can use the postal code as a starting point for address extraction.  The post code is the most distinctive identifiable componet of an address and was a manditory requirment of the addresses I was to extract.  My approch was to identify valid formated post codes, and then calculate the remainer of the address from there.

Based on this, I was able to formulate a regular expression pattern to perform the address extraxtion which can be split into the following components:
  • Flat Number (optional)
  • AddressLines (hidden)
    • Door Number (optional)
    • AddressLines (optional)
  • Post Code (mandatory)
I used a hidden/un-named group to combine the door number and address lines regex.  This ensures that if a door number is found, it will control the length of the address lines.

Post Code Regex

Based on the information from wikipedia regarding uk post code formatting (wikipedia-Postcodes_in_the_United_Kingdom.)  The format is comprised of an outward code and an inward code seperated by a space.  I'm aware the space can often be omitted.

The outward code contains an area code of one or two alphabetical characters followed by a district code which is a single digit, then optionally a single alphanumeric character. 

The inward code is made up from the sector code which is a single digit followed by the unit code which is two alphabetical characters.

To locate a valid UK post code I ended up with the following regex:
(?<PostCode>(?<Area>[A-Z]{1,2})(?<District>\d\w?)\s*(?<Sector>\d)(?<Unit>[A-Z]{2}))
 

Address Lines Regex

To find the address lines, I'm looking for between 1 and 4 blocks of text seperated by comma which preceed the Post Code.

The regex I used for this was: 
(?<AddressLines>([A-Z-''\s]{2,}[,\.\s]){1,4})
 

Door Number Regex

To find the door number, I used an assumption that it must start with a digit, but could contain a leter (example 2b or 7a.) I also allowed the door number to be either space or comma seperated from the address.

To find the door number, I used regex:
(?<DoorNumber>\d+[,\s]+|\d\w[,\s]+)
 

Flat Number Regex

For the data I was working with, flat numbers always followed the word flat.  For that reason I was able to look explisitly for the literal word Flat (case-insensitive) and attempt to find a flat number in the following.  As with door number, I permitted a flat number to be suffixed with a letter.

The regex I used to find the Flat Numbers was:
(?<Flat>Flat\s?(?<FlatNo>\d\w*)\s?,?\s?)
 

Full Regex

So, all of the above regex components combined (with an unnamed group to combine Door Number and Address Lines) resulted in the following regex:
(?<Flat>Flat\s?(?<FlatNo>\d\w*)\s?,?\s?)?((?<DoorNumber>\d+[,\s]+|\d\w[,\s]+)?(?<AddressLines>([A-Z-''\s]{2,}[,\.\s]){1,4}))?\s?(?<PostCode>(?<Area>[A-Z]{1,2})(?<District>\d\w?)\s*(?<Sector>\d)(?<Unit>[A-Z]{2}))

I was able to perform the regex using a clr function and return a table containing the match result along with the components of the address.

Results

When given the task, I was not expecting to do well beyond post codes.  The post code matching was almost perfect except for invalid or typo's in the freetext.  However, I got some very impressive results.  Any address with a door or flat number extracted perfectly.  However, those without where hit and miss, sometimes I grabed to much text preceding the post code and sometime not enough.

Conclusion

I'm not a regex expert, I'm sure it could be improved or optimised.  I'm also sure I may have missed some posible symbols which are valid addresses or other posible formatting of flat and door umbers.  However, for the task and dataset I was working with, the extraction was far better than expected.

I do have a few ideas how it could be improved, however, I have meet my requirement and the project has completed.  So for now, this is it.

Friday 22 May 2020

R2D2 Animated and in THREE.JS

My efforts have payed off, I have been successful in exporting my R2D2 from Blender to THREE.JS and Animating him.  I have also learnt a lot more about the THREE.JS animation system.

Monday 18 May 2020

I made R2D2 (in Blender..)

I'm not creative or artistic.  I have don't see myself making interior designs or 3D rendered works of art.  But I am increasingly using 3D models in my visualisation work (and playing with AR.)  So I'm highly dependant upton the 3D models I can get for free or purchase cheaply.

This is a problem for me...  As I have a very small budget and many of the things I've wantted are way out of my budget.  And so, I needed to learn how to make some of the models I need myself.

So far, I have made a Donut, an Anvil, a Chair, a Coke Can, Titanic and R2D2.  I can see that I will always be an ammeter at 3D modeling, but I'm happy with my results.

I had no real need for R2D2, but I felt he was an interesting subject to learn and practice my skils I'd learnd from YouTube (most specificly Blender Guru.)  

I made him twice, the first time was based on reference photos from Google Images, this was ok, but I cut a lot of corners...  The second attempt was based on images and blueprints from https://astromech.net/.  He's not entirly acurate, and Not fully finished, but he will do and I have learnt alot.

R2D2 3D Model

My reason for modeling R2D2 was to improve my skills.  I had attempted a few modeling projects for objects I wantted, but they failed (attempt 2 coming soon). I ultimatly wanted to animate R2D2, but that's not currently going very well either.

For now, I'm just happy with the model as an early result in my 3D modeling skills.

Clone of a SkinnedMesh (loaded Model) in THREE.JS with animations

One of my biggest annoyances with using loaded models in THREE.JS was the failure to clone them, and more importantly, animate the clone.  Without the ability to clone a skinned mesh or loaded model and then independently animate it, I was forced to keep loading the model from file.  This was very slow and resulted in load loading times.

I tried everything...  I discovered a clone method on SkeletonUtils which would supposedly work. but I just got errors or a mesh that would not animate.  I even found functions written and published by other people, but these also did not seem to work.  I did my best to optimise the load from file to speed things up, but it was useless.

So, I created my own function to perform the clone operation...  Being an ammeter with only a simple understanding of the THREE.JS object model, I set about writing the function to clone any Object3D.  I had observed that many of the models I was working with featured a hierarchy of objects of types Group, SkinnedMesh or Bone (others currently unsupported, but probably a simple change.)  I then used comparison techniques and trial and error until things started to work.

I then created a function specific to the SkinnedMesh type, because I needed to copy some important properties only relevant to this type.  Finally, I created a function to copy any userData.

The functions are a work-in-progress and might need a tweak to work with other models, but it dramatically helped my project.

Here is the three functions I ended up with...

    public cloneObject3D(objTHREE.Object3DparentTHREE.Object3D): THREE.Object3D {
        let retTHREE.Object3D = null;
        switch(obj.type) {
            case "Group"ret = new THREE.Group(); break;
            case "SkinnedMesh"ret = this.cloneSkinnedMesh(obj as THREE.SkinnedMeshparent); break;
            case "Bone"ret = (obj as THREE.Bone).clone(); break;
            defaultconsole.log('Unknown Clone Type: ' + obj.type); ret = new THREE.Object3D();
        }
        obj.children.forEach((c,i=> {
            ret.add(this.cloneObject3D(c,ret));
        });
        if (obj["ID"]) { ret["ID"] = obj["ID"]; }
        ret.name = obj.name;
        ret.position.set(obj.position.x,obj.position.y,obj.position.z);
        ret.rotation.set(obj.rotation.x,obj.rotation.y,obj.rotation.z);
        ret.scale.set(obj.scale.xobj.scale.y,obj.scale.z);
        ret.quaternion.set(obj.quaternion.x,obj.quaternion.y,obj.quaternion.z,obj.quaternion.w);
        ret.matrixWorldNeedsUpdate = obj.matrixWorldNeedsUpdate;
        ret.userData = this.cloneAny(obj.userData);
        return ret;
    }

    public cloneSkinnedMesh(objTHREE.SkinnedMeshparentTHREE.Object3D): THREE.SkinnedMesh {
        let geo = obj.geometry.clone();
        let mat = obj .material;
        mat = (obj.material as THREE.MeshPhongMaterial).clone();
        let ret = new THREE.SkinnedMesh(geo,mat); 
        let bones = new Array<THREE.Bone>();
        
        obj.skeleton.bones.forEach((b=> { 
            let nb = parent.getObjectByName(b.nameas THREE.Bone;
            bones.push(nb); 
        });

        ret.skeleton = new THREE.Skeleton(bones);

        obj.skeleton.boneMatrices.forEach((bm,bmi=> {
            ret.skeleton.boneMatrices[bmi] = bm;
        });
        obj.skeleton.boneInverses.forEach((bi,bii=> {
            ret.skeleton.boneInverses[bii] = bi;
        });
        obj.bindMatrix.elements.forEach((e,ei=> {
            ret.bindMatrix.elements[ei] = e;
        });
        obj.bindMatrixInverse.elements.forEach((e,ei=> {
            ret.bindMatrixInverse.elements[ei] = e;
        });
                
        return ret;
    }

    public cloneAny(objany): any {
        let ret = {};
        Object.getOwnPropertyNames(obj).forEach((pn=> {
            ret[pn] = obj[pn];
        });
        return ret;
    }

Friday 24 April 2020

Projecting a point onto a sphere

Maths is not a strong skill of mine, but I'm not afraid of it either.  A mathamatical poblem I recently needed to solve was to plot a point in 3d space on a sphere.

I needed to project points using the latitude and longitude coordinate system on both a plane and a sphere.  The plane was simple, but the sphere was more tricky.
Point on Sphere

The formula I settled on is bellow.  I had to add 90° to the latitude otherwise I found it would only plot for one hemesphere.
y = radius * Math.cos(latitude+90°);
x = radius * Math.cos(longitude) * Math.sin(latitude + 90°);
z = radius * Math.sin(longitude) * Math.sin(latitude + 90°);

Monday 20 April 2020

Visualising Earth in PowerBI Custom Visual

Early on in my 3D visualisation experimentation was a desire to recreate the PowerMap experiance.  I eventually managed to find a source of land and country boundaries, which I was able to project into a 3D scene and then plot points based on latitude and longitude.
Country data as map
After many hours searching, experimenting and crying, I found a formula for projecting the points onto a sphere so I could create the globe.
Country data as sphere
But my map data was not perfect, and I wantted a more realistic globe image.  So I downloaded some image data from NASA at https://visibleearth.nasa.gov/.  There Blue Marble collection of images was perfect for my needs.
3D Earth Visualisation
Daytime Globe View

Nighttime Map Visualisation
Night Map View

Using my limited experiance and skills of 3D and PowerBI visual development, I was able to create a PowerBI Cutom Visual with a much more realisitic look and feel.  Points can be plotted by latitude and longitude, or a country can be highlighted by name, ISO2 or ISO3.


3D Earth Visualisation

My projection code (which is the key to making this work..) is as follows:

    private projectAsMap(longnumberlatnumberrnumber): THREE.Vector3 {         let z = long / 180.0;         let y = lat / 180.0;         return new THREE.Vector3(r, -y, -z);     }     private projectAsGlobe(longnumberlatnumberrnumber): THREE.Vector3 {         let s = -long * (Math.PI / 180);         let t = (lat + 90) * (Math.PI / 180);         let x = r * Math.cos(s) * Math.sin(t);         let z = r * Math.sin(s) * Math.sin(t);         let y = r * Math.cos(t);         return new THREE.Vector3(xyz);     }