Friday, March 17, 2017

Typescript/JavaScript Angular Problem: Hashmap a dictionary of rescaled one dimensional coordinate values to their corresponding indices for a position based array mapping and more

Okay, so the title is rather a big one, but the problem goes like this:

You've had to squeeze your data down in such a way so that it fits into your canvas graphic...that is, it makes little sense if you have big numbers that can't be viewed because their plot values are outside of the dimension of your screen.  This problem is of 'squeezing' the data is otherwise re scaling it so that it fits into visual dimensions that can be read.  Its really not a big deal doing that since you can refactor a plot without changing its shape/form attributes by using a global scale factor.  But let's say you wanted to have a quick and easy search algorithm that matches a screen based coordinate that a user has supplied, say from mouseover position that relates to a position on the graph or at least as directly related to your big data.  How to do this?

As it turns out you may have stored your big data, in some sort of collection type that contains points which may have something like: x, y in 2 dimensions, and this collection type may be structured in the form of an array.  The problem is that with any mouseover, your first inclination may be to search the set of points and then break at a common match, but this is slow!  I say this since you are constantly search iterating points to find the match based on a screen position that is supplied.  Why not create an inverse map on the set of points and hashmap these?

As it turns out you can do it in Typescript/Javascript, but as I found out, keys say with the {} type string values.  If your data is on the other hand given by positions which are 'number' types you'd first have to likely Math.round(), Math.floor() or Math.ceiling your numbers.  Then you'd convert this to string using the position.x.toString(),  'number' types have a .toString() method.  Then you'd key the value while storing its array index in value position.

A sketch:

    public setScreenXCoords(){
        //called after screen coordinates have been setSceenXCoords
        //and that this.points is a screen coordinate set.  
        var i = 0;
        for (let pvec of this.screenpoints){
            let x = pvec.x;
            x = Math.round(x);
            /*
            console.log("key: ");
            console.log(x);
            console.log("value");
            console.log(i);
            */
            this.screenToIndex[x.toString()] = i;
            i += 1
        }
    }

In a given data range set of points, it is important to keep in mind that keying position data means also that truncation (by floor, rounding, or ceiling a number) may necessarily supply more than one position for a given key, and for this you may need to bucket the values in an array, and provide additional searching algorithms in refining a search, but at least this method provides nice fast lookup position addressing.

So when you search you need to account for undefined key values.  These are screen positions that do not have a corresponding key in, for instance, inverse2dVectorsMap.  For this, you simply omit the user supplied position until they have sufficiently toggled a position that corresponds to a point on the data set.

And example sketch:

    public getScreenPoint(xposnumber){
        let xpostr = xpos.toString();
        if (xpostr in this.screenToIndex){
            return this.screenToIndex[xpostr];
        }
        return undefined;
    }


Then filter 'undefined' return values relative to non 'undefined' ones.

For example:

    private mouseMoved(eMouseEvent){
        //(mousemove)="mouseMoved($event)"
        console.log(e.offsetX);
        let xstr = e.offsetX.toString();

        
        console.log("screen index: ");
        
        if (e.offsetX != undefined){
            let ind = this.dataCharts[0].getScreenPoint(e.offsetX - 80.0);
            console.log(ind);
            if (ind != undefined){
            this.pointindex[0] = ind;
            this.pointindex2 = ind;
            }
        }
    }

Thursday, March 16, 2017

Tip for determining an angular dom event

Dom events in html5 do have a translation to Angular, but it may not be immediately obvious.  For instance, in Angular the reference call (click) is equivalent to onclick for the corresponding dom event in Html5 outside of Angular.  As it turns the conversion process may follow the rule:
add parenthesis () and then drop the prefix "on"  so "onclick" becomes "(click)" or "onmousemove" becomes "(mousemove)".  This seems to be a general translation language pattern between Angular and non Angular usage in Html.

Sunday, March 12, 2017

Programming complications and work around in Angular

   In a previous post, I provided a simple recipe for passing simple type arrays to avoid more formal data binding in Angular.

Recently a problem emerged where in Typescript (translated to JS), I were instancing randomly generated class/struct data called lineData in working with a visual graph/charts data interface and this data was instanced inside the class of two canvas selector directives from a parent component controller.   My intent were to pass an array object of this class namely lineData[]

The problem:
When instancing a class array type of this data and while passing the array object of lineData, or  lineData[], I was repeatedly generating errors in the contstructor and ngOnInit() or ngOnChanges() methods when attempting to write data to either directive instance.  The error generated was an 'undefined' when accessing the lineData[] object even though it were supposedly populated in the constructor call with data.  Strangely when not passing from the parent controller component to the individual child directives, lineData[] instanced at the child level with non injection would not generate non persistence problems as seen in the parent to child injection case.

Solution:
I still needed to pass and coordinate data between two child directives on the lineData[] array object, so instead, I opted to generate the random lineData[] at the parent component controller level and then pass this to each child directive where data persistence would suffice.  This in retrospect still seems a bit troubling to me, one since evidently manipulating and instancing data in the child directive fails as an instancing source, but not if such origins are in the parent component controller class.  Technically though it should work, it my suspicions are that the ngOnChanges() method is cleaning the lineData[] object (beyond the constructor call) with the changes in the parent level controller binding of this object to its child directives.  Technically, I haven't set anything at the parent level to reset lineData[] (i.e., removing data or splicing or whatever), but the mystery remains as to what were occurring here.

Friday, March 3, 2017

Cool Trick in Angular to avoid formal data bindings

   How should I be passing parameter data, and how do I exactly do it without defining a directive or component?

  Let's say you wanted to defined a child class structure that is merely a object process that does something but you weren't as interested in angularizing syntax to pass parameter data.  There is a way to do this.  The secret goes to C and C++ and other non scripting high level languages that make use of pointers for referencing the memory of object data.  As it turns out in scripting languages commonly, though they don't make use of point or call by referencing exactly, but you can still do it!  


Scripting languages  (e.g., Java, Javascript, and Python for instance) are locked out from call by referencing on:

-number, float, integer, boolean, and so forth object types.  


But not on:

-array, list, hashlist, map, dictionary, class, struct, string, and so forth.  


Thus if you wrap a locked object type in one of the non locked out types such as an array, you can pass parameter data by modification.

The beauty of doing a 'binding' this way is that it is quite simple in terms of syntax.  Literally you use an object wrapper that does the same thing.  

I have avoided defining event listeners for parameter data changes.  Namely in my particular case synchronizing animation loop start and stops between two angular directives, the loop itself would act as an event listener thus omitting the need in explicitly defining an event detection structure in angular.  As it turns out though object wrapped types, I believe, are not detected by implicit changes say in the array such as modification of the array at a given already assigned index.  Thus defining event listeners in angular will likely have work around if you plan on constructing event listeners in conjunction with object wrapping methods that I have described.  

You can construct event listeners (without defining these formally) also by using recursion calls:

method(){
   requestAnimationFrame(()=>this.method())

Technically its an animation timer, but it should be safe for event handling processes.  You'd just need to define breaks if you want to pause or stop this event handler (e.g. a boolean structure that prevents reiteration of the recursion call).

Friday, February 17, 2017

Recipe for creating parallax effect of background image in Angular 2.0 Typescript

import { HostListener, Component, OnChanges, Directive, Input, Output, EventEmitter, SimpleChange, ElementRef} from '@angular/core';

Here is the directive:

@Directive({
    selector: '[track-scroll]',
    //host: {'(window:scroll)': 'track($event)'},
 
})

export class TrackScrollComponent {

  @Output() notify: EventEmitter = new EventEmitter();
  @HostListener('scroll', [''])
    track() {
        console.debug("Scroll Event");
        //console.debug(this._elementRef.nativeElement.scrollTop);
        this.notify.emit(this._elementRef.nativeElement.scrollTop);
    }
   constructor(private _elementRef: ElementRef) {}
}

It is worth noting that you'd want an event emitter which communicates changes in track-scroll directive back to the parent component.

Now as indicated in the previous posting on implementing in the parent component html you'd modify the tag with a on notify event handler:

<nav track-scroll (notify)='onNotify($event)' >
   <nav class='backgroundimageclass' style.background-image.position-y = "{{this.scrollpos}}px"
</nav>


Now in your parent component you'd need to make sure to have  scrollpos set as class instance object type number and ensure that the event function is defined with updates to scrollpos in this onNotify function:

@Component({
    moduleId: module.id,
  selector: 'parentcomponent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],

})

export class ParentComponent{
   scrollpos: number = 0.0;

   onNotify(message:number):void {
        this.scrollpos = message*0.2;
        console.log("hitting!");
        console.log(message);
    }
}

Thus the child directive is transmitting back through "message" the scroll position which is assigned to the parent class object scrollpos and this class object is interpolated back into the parent html style.background-image.position-y value...note we are scaling to a fractional value 0.2 the amount of change resembling parallax so that the background image is not equal to the shift in text.

Here is an example parent.component.css sheet for adding the background image:

.backgroundimageclass{
     background-image: url(../assets/MainNavHeader_V01.png);
    /*background: rgba(76, 175, 80, 1.0);*/
    /*background-color: black;*/
    /*background-size: 1200px 780px;*/
    padding-top: 10px;
    background-blend-mode: overlay;
    /*min-width: 1236px;*/
    /*min-height: 298px;*/
    /*width: 1236px;*/
    /*height: 298px;*/
    position: relative;
    left: 50px;
    -webkit-mask-image: -webkit-gradient(linear, left 70%, left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
    /*-webkit-mask-image: -webkit-gradient(linear, left 30%, left top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));*/
    /*background-position-y: 100px;*/
    /*background-repeat: no-repeat;*/
    /*overflow: auto;
    clear: both;*/
}

I've included in this case a little webkit alpha mask also on the background image which feather fades the bottom border for instance.

Note my import statement above is done so assuming the parent and child directive are in the same file.  If you wanted to separate these, just make sure to update your import statements.

Please read my previous post for additional information on implementing the child directive in the parent.  Namely, you'll want to ensure that the directive is actually done through the app.module.ts declarations for most current versions of Angular 2.0

A little bit of GIS information: Acquiring DEM heightmap renderings and colorization



First it should be mentioned that if you are doing terrain colorization of your choosing, you may already be familiar with or not http://viewer.nationalmap.gov/ in obtaining both satellite terrain imagery and/or heightmap data.  The big challenge, however, comes in how to re purpose this data in the context of say a 3D modeler like Blender.  Adding that I would recommend a program called QGIS (http://www.qgis.org/en/site/)  which provides GIS rasterization (rendering) services specifically tailored to things like heightmap mosaicing and a lot more.  Mosaicing is particularly useful because often heightmaps tend to be parsed by coordinate range addresses.  Without any GIS program, you'd have to have some alternate graphics program properly align and stitch these mosaics together in their proper coordinate range addresses otherwise (which is not needed).  Secondly QGIS equalizes heightmap mosaics when they are merged into one heightmap handling overall differences between the two maps (which may not be absolute in the context of luminosity and light values over the range of greyscales for instance in greyscaling formats by analogy). 

Other prerequisites:  
In Ubuntu installation goes as follows:
https://trac.osgeo.org/ubuntugis/wiki/QuickStartGuide
apt-get install cgi-mapserver
Because a given heightmap is actually given by measurements which include the surface of the Earth which is curved we will need to however project a given map flat...in this case GDAL warp packages (doing this task) will need flat projection coordinates under a lambert-conformal conic transformation.   Don't worry there is a utility in java script to handle this task...though you will need access to java script.  I like node.js which makes use of package manager called npm to handle these sorts of packages for easy to directory installation.

I recommend utilizing a java script called Proj4js and if you use node.js the node package is proj4 (see https://github.com/proj4js/proj4js) which can be installed via npm (node package manager) at your terminal command line :
Using this command will install the node package in the given root directory at prompt.

npm install proj4

you can run node at terminal, once installed typing:
$ node

once node is running in terminal then:

> var proj4 = require("proj4");

You may also find it handy for input and output coordinate parameters using information given from
spatialreference.org

next we define the destination projection given from spatial reference.org

>proj4.defs('EPSG:2228',"+proj=lcc +lat_1=37.25 +lat_2=36 +lat_0=35.33333333333334 +lon_0=-119 +x_0=2000000.0001016 +y_0=500000.0001016001 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs");

if you type then 'proj4' and hit enter you should see the definition given..
with key value 'EPSG:2228'.

The source rule is already defined for longitude-latitude coordinates:
which is 'EPSG:4326'

so conversion at prompt is as follows:
> proj4('EPSG:4326','EPSG:2228',[-118,32.0170]);

// yields [ 6872583.317630408, 433558.88221227354 ]

You can use this to find projection coordinates from one coordinate system to another.  That being said QGIS also has handlers for Relief, Hillshade and Slope, Roughness, TRI, and TPI colorization and plugins in provisioning custom color gradients alongside providing users the ability to customize color gradient sets.

So the short workflow synopsis goes as follows:

With DEM dataset downloaded, you can load, for instance, .img sets on a new QGIS project session as follows:
Assuming that you have downloaded multiple filesets for a given geographic selection range, you may want to merge your heightmap files (merging these will equalize this files relative to one another...otherwise jump discontinuities may likely occur between them).

Merging Mosaics
1.  Choose 'Raster>Miscellaneous>Merge...'.
2.   Pressing 'ctrl' button select all necessary source files to be merged for source.
3.  Assign a destination file.  You may likely need to make sure the destination file type matches the source (this is not always given by default).
4.  Press 'Ok'.

All is done well and you should see a mosaic composition of all merged images shown in the QGIS visual browser window.

Selection cropping by latitude/longitude coordinates
1. Choose 'Raster>Extraction>Clipper'
2. At Dialog, longitudinal coordinates are X and latitude coordinates Y...or alternately you can select on the map visually coordinate boundaries.
3.  Assign destination file. You may likely need to make sure the destination file type matches the source (this is not always given by default).
4. Press 'Ok'.

Projection warp flattening the data set

1.  'Raster>Projection>Warp...'
2.   Default lat/long coordinate source SRS is usually provisioned depending on your file type, but you will likely need to indicate the target SRS (e.g.,  'EPSG:2228' above projection flattens coordinates for the state of California).
3.  As above source (e.g. merged file above) is selected and destination name assigned.
4.  Press 'Ok'.

Generating Hill Shade

Reading the scroll position of an html element in Angular 2.0 Typescript

I've seen some implement a component, which you can can do but this expects (to my knowledge) an html template.  I've used instead directive (which a component is but without the requirement of having an associated html template).

Here is my directive:
import { HostListener, Component, OnChanges, Directive, Input, Output, EventEmitter, SimpleChange, ElementRef} from '@angular/core';

@Directive({
    selector: '[track-scroll]',
    //host: {'(window:scroll)': 'track($event)'},
 
})

export class TrackScrollComponent {
  @HostListener('scroll', [''])
    track() {
        console.debug("Scroll Event");
        console.debug(this._elementRef.nativeElement.scrollTop);
    }
   constructor(private _elementRef: ElementRef) {}
}

I did use injection of the Element Ref, or as it is instanced from the 'div' tag the div ElementRef.

All directives in RC 6.0 (?) + go to the ngModule, or otherwise assigned in parent component.

Thus in my app.module.ts

@NgModule({
  imports: [ BrowserModule, AppRouting ],
  declarations: [TrackScrollComponent],
  bootstrap: [ App ]
})

Implementing in your component then goes to yourcomponent.html or template as follows:


<div track-scroll> </div>

 Sorry for some of the imports I hadn't tested which one were exclusively needed for this howTo.

There is mentions about not working directly with ElementRef, but at the moment I wanted to provide clarity for solution as opposed to creating added confusion for something that really should be simple.

Oblivion

 Between the fascination of an upcoming pandemic ridden college football season, Taylor Swift, and Kim Kardashian, wildfires, crazier weathe...