Tuesday, April 17, 2012

OpenLayers Zoom Fade + Resize Transition Effect

Taking the inspiration from Leaffet which uses modern browsers' css3 transition effect to add a fade effect to map zoom/pan, I quickly customised OpenLayers to do similar thing.

The fade effect is supported well in modern version of Firefox and Chrome, as well as in IE10+.
For IE 6, 7 and 8, I use the javascript timer to transition the opacity of a tile.

Get the code from
https://github.com/lydonchandra/openlayers/blob/release-2.11/lib/OpenLayers/Tile/Image.js
or
OpenLayers-distro/OpenLayers-2.11/lib/OpenLayers/Tile/Image.js



    show: function(isResize, ratio) {

        if( OpenLayers.Util.getBrowserName() === 'msie' ) {

                if(  isResize &&  
                        this.frame.style.display === 'none' &&
                        ratio !== undefined && ratio > 1 ) {

                            //console.log( 'resizing, ratio==' + ratio + ' display==' + this.frame.style.display );

                            this.frame.style.display = '';

                            // style.opacity is only supported by IE9+
                            this.frame.style.opacity = 0;

                            // have to use filter for IE7 and IE8
                            this.frame.style.filter = 'alpha(opacity=' + 0 + ')';
                            var theFrame0 = this.frame;
                            window.setTimeout(
                                    function() {
                                        theFrame0.style.opacity = 0.5;

                                        theFrame0.style.filter = 'alpha(opacity=' + 50 + ')';
//                                        window.setTimeout(
//                                                function() {
//                                                    theFrame0.style.opacity = 0.4;
//                                                    theFrame0.style.filter = 'alpha(opacity=' + 40 + ')';
//                                                    window.setTimeout(
//                                                            function() {
//                                                                theFrame0.style.opacity = 0.6;
//                                                                theFrame0.style.filter = 'alpha(opacity=' + 60 + ')';
//                                                                window.setTimeout(
//                                                                        function() {
//                                                                            theFrame0.style.opacity = 0.8;
//                                                                            theFrame0.style.filter = 'alpha(opacity=' + 80 + ')';
//                                                                                      

                                                                                    window.setTimeout( function(){

                                                                                        theFrame0.style.opacity = 1;

                                                                                        theFrame0.style.filter = 'alpha(opacity=' + 100 + ')';

                                                                                    }, 100);

                                                                          

//                                                                        }, 100
//                                                              
//                                                                );
//                                                              
//                                                            }, 100
//                                                  
//                                                    );
//                                                  
//                                                }, 100
//                                           );

                                       

                                }, 100 );

                } else if( !isResize && ratio === 1 && this.frame.style.display === 'none'){

    //                console.log('resizing, ratio==' + ratio);
   
                    this.frame.style.opacity = 1;
                    this.frame.style.display = '';
                    this.frame.style.filter = 'alpha(opacity=' + 100 + ')';

                }  else {

//                console.log('else --- ratio==' + ratio + ' display==' + this.frame.style.display + ' isResize==' + isResize );
//                 this.frame.style.opacity = 1;
//                 this.frame.style.display = '';
//                 this.frame.style.filter = 'alpha(opacity=' + 100 + ')';

                if( this.frame.style.display === 'none' ) {

                        this.frame.style.display = '';

                        // style.opacity is only supported by IE9+
                        this.frame.style.opacity = 0;

                        // have to use filter for IE7 and IE8
                        this.frame.style.filter = 'alpha(opacity=' + 0 + ')';

                        var theFrame0 = this.frame;

                        window.setTimeout(

                                function() {

                                    theFrame0.style.opacity = 0.5;

                                    theFrame0.style.filter = 'alpha(opacity=' + 50 + ')';
                                  

//                                    window.setTimeout(

//                                            function() {

//                                                theFrame0.style.opacity = 0.4;
//                                                theFrame0.style.filter = 'alpha(opacity=' + 40 + ')';
//                                                window.setTimeout(
//                                                        function() {
//                                                            theFrame0.style.opacity = 0.6;
//                                                            theFrame0.style.filter = 'alpha(opacity=' + 60 + ')';
//                                                            window.setTimeout(
//                                                                    function() {
//                                                                        theFrame0.style.opacity = 0.8;
//                                                                        theFrame0.style.filter = 'alpha(opacity=' + 80 + ')';

                                                                                window.setTimeout( function(){
                                                                                        theFrame0.style.opacity = 1;
                                                                                        theFrame0.style.filter = 'alpha(opacity=' + 100 + ')';

                                                                                }, 200);

//                                                                    }, 100
//                                                            );
//                                                        }, 100

//                                                );
//                                              
//                                            }, 100
//                                       );

                            }, 200 );

                }
            }
        }

        else {
                                       

          if(  !isResize &&   
   
                  this.frame.style.display === 'none' ) {
   
                  this.frame.style.opacity = 0;
                this.frame.style.display = '';
                this.frame.style.transition = 'opacity 0.5s ease-in';
                this.frame.style.WebkitTransition = 'opacity 0.5s ease-in';
                this.frame.style.MozTransition = 'opacity 0.5s ease-in';
       
                var theFrame = this.frame;
                setTimeout( function() {
       
                // have to give it some time and then set the opacity
                // otherwise the transition effect won't kick in
                theFrame.style.opacity = 1;
                }, 50 );
   
            } else {
   
                this.frame.style.opacity = 1;
                // remove transition effect so it doesn't get applied everytime,
                // we control when it gets applied (only when showing the tile as above)
                this.frame.style.transition = '';
                this.frame.style.WebkitTransition = '';
                this.frame.style.MozTransition = '';
                this.frame.style.display = '';
            }
       }

       

        // Force a reflow on gecko based browsers to actually show the element

            // before continuing execution.

            if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,

                    this.layer.transitionEffect) != -1) {

                if (OpenLayers.IS_GECKO === true) {

//                    this.frame.scrollLeft = this.frame.scrollLeft;

                }

            }

        }

Monday, March 5, 2012

OpenLayers + PhoneGap + JQuery

As published in http://lydon.ch/content/openlayers-phonegap-jquery 


http://ozmin.es is written using OpenLayers, JQuery, and JQueryUI.

It was easy to have http://ozmin.es as iPad or iPhone app using PhoneGap,

where the difficult thing is to setup PhoneGap to know where iOS SDK is!

The next step is to investigate JQuery Mobile on iPad and iPhone and also Android and maybe Windows 7 Phone

Wednesday, February 8, 2012

How do I organize my GIS projects?

from http://gis.stackexchange.com/questions/18199/how-do-i-organize-my-gis-projects


Base Files/DBS

  • These are files that are "raw" in nature and constitute the base of all my analysis
  • These files, databases, and data are hosted outside of my projects folder, and are hosted on my internet server, local computer, and dropbox. I always have access to them, and they are very organized, dis and aggregated. You'll spend a lot of time organizing these.
  • I put them all in databases whether in Arc or PostGIS.
  • To each table, I add 3 fields in the table itself or the meta data: DATE_OBTAINED, DATA_DATE, SOURCE_NOTES
  • Also Base files could be queries of multiple other tables. For example, a table could aggregate all the traffic count I obtain into one large query/table.
  • I also put here all other data that I find scouring the internet.
  • I NEVER DO ANY DIRECT ANALYSIS ON ANY OF THE FILES IN THE BASE FILES

Project Files

  • All my project files go in a my_projects folder. It contains everything related to that project as in, if I copy and paste that folder somewhere else, it will contain everything.
  • Usually I have the following structure:
    • my_project/
      • admin/
      • communication/
      • raw_data/
      • analyzed_data/
      • output_data/
      • from_client/
      • FINAL/
      • code/
      • some_document_date_time.doc
      • README
  • Slowly I've been moving to a local GIT. (you can even host it locally or on your own server). The reason I do not put it on GitHub is that github has a 1.2gb limit which is useless for GIS analysis
  • For my projects, I usually replicate all the GIS tables that I need for my analysis into a new db: project_whatever.
  • 9 times out of 10, I work only in shp files and I save all my GIS (images, excel, coordinates, etc) to my projects/my_project/raw_data, projects/my_projects/analyzed_data, andprojects/my_projects/output_data.
  • When a project is complete, I put the final submitted copy inmy_projects/FINAL/date_submitted
  • For my MXD, I usually save to a new MXD every 2 or 3 hours my_proj_dec_22_11__13_20.mxdfor example
  • For Ms Word documents, illustrations, and mostly editing documents, they go in my_projects folder such as RFP_TENDER_Dec_22_11__11_15.doc and draft_ver5_Dec_31_11__12_30.doc. Again all my final deliverables go in in the FINAL folder
  • For R, Python code and some C#, it gets a bit tricky, as I host it outside of the project but with a working copy to my_projects/code folder. I do this as most of the python code is reusable. If you put all your python code besides the projects, you'll forget about them. Also, all my python code goes on github.
  • To me project files include any file types including time tracking, communications (I save all my emails as .msg files), I log all our verbal communications in a word file, and I put all those files my_project/communication
  • With ArcGIS use Models, LYR, and "save selection as a new shp layer". These tools will make it easy to store files in smaller formats, reuse files, and with models, be able to use something in another place.

Final Output

  • Each project when finalized gets zipped and put on my external harddrive.
  • All final products are converted to files from Tables, and to PDF from all other formats.
  • Every Project I do, gets printed for a hard copy backup

The Bottom Line

  • Each person uses multiple and different software and tools. A lot of people I know get organized using basecamp, Harvest, or any other multitude of tools. Also people have different working habits and OCD tendencies. I'm fairly obsessed with getting stuff organized maybe a bit more than others. So develop the system that causes you the least stress while guaranteeing you'll be consistent in applying and updating it
  • Backup and replicate everything
  • Don't work directly on your raw / base data
  • For your projects always use a replica file, as data changes over time, and you don't want to be scrambling to find the base_layer_2006.shp.
  • each my_projects folder must have a README text file that you edit it while you're doing the projects to give some basic information that you know you'll forget later when you visit the project 2 years down the road

Tuesday, January 17, 2012

Orbeon XForms and ANZLIC Metadata Editor

 http://orbeon.com/ has a very good platform to build XForms based web-application.

This is very suitable for an ANLIC Metadata Editor which should have the same or more functionality than
xMET (eXtensible Metadata Editing Tool)
http://www.mymaps.gov.au/xmet/1.0t/xmet-setup.exe

Other XForms implementation:
1. FormFaces, a javascript implementation of XForms Engine
2. AJAXForms, XSLTForms, betterFORM, Chiba and Orbeon Forms

Wednesday, January 4, 2012

Broadleafdemo-1.5 & IBM Websphere v8.5

Once you got broadleafdemo running in JBoss 7 as per http://lydonchandra.blogspot.com/2011/12/running-broadleaf-ecommerce-150-demo-in.html , then it should be trivial to deploy it onto IBM Websphere v8.5.

1. Go to Websphere admin console http://host:9043/ibm/console
2. Applications > New Application > New Enterprise Application
3. Choose "Local file system" and select a compressed broadleafdemo.war (not exploded).
4. Choose "Details" settings, and make sure you map broadleafdemo.war onto /broadleafdemo context (and not onto the root context / )
5. Save and start broadleafdemo.

Wednesday, December 28, 2011

Using Glassfish built-in connection pool (rather than dbcp or c3p0)

From http://skytteren.blogspot.com/2009/06/using-mysql-connection-pool-in.html


Using MySQL connection pool in Glassfish V3
I tried with a simple data source in Spring, but it isn't meant for production environments. So I wanted to move from:

<bean id="simpleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/database"/>
<property name="username" value="database"/>
<property name="password" value="s3cr3t"/>
</bean>

to:

<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/databasePool" />
</bean>

This can be done from within Glassfish admin, by creating the connection pool with the specified jndi name.

c3p0 connection pool in broadleafdemo (instead of dbcp)

Why c3p0 ?
The old dbcp (1.2.2 is used in broadleafdemo) is less robust than c3p0.
http://stackoverflow.com/questions/520585/connection-pooling-options-with-jdbc-dbcp-vs-c3p0
Will do some performance testing with dbcp 1.4.

1. Open broadleafdemo.war\WEB-INF\applicationContext-demo.xml
2. Modify your webDS and webStorageDS beans 
2a. change the class to com.mchange.v2.c3p0.ComboPooledDataSource
2b. change property name to driverClass (from driverClassName)
2c. change property name to jdbcUrl (from url)
2d. change property name to user (from username)

<bean id="webDS" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/broadleaf" />
<property name="user" value="user" />
<property name="password" value="password" />
</bean>
    <bean id="webStorageDS" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/broadleaf" />
<property name="user" value="user" />
<property name="password" value="password" />
</bean>

3. Download c3p0 from http://sourceforge.net/projects/c3p0/files/latest/download , extract, and copy c3p0-xxxx.jar (c3p0-0.9.1.2.jar at the time of this writing) into broadleafdemo.war\WEB-INF\lib

4. (Optional) You can also remove commons-dbcp.jar from broadleafdemo.war\WEB-INF\lib as it's no longer used.

References:
http://stackoverflow.com/questions/3002899/spring-configuration-of-c3p0-with-hibernate
http://stackoverflow.com/questions/520585/connection-pooling-options-with-jdbc-dbcp-vs-c3p0
http://sourceforge.net/projects/c3p0/