Wednesday, June 16, 2010

Horizontal and vertical alignment with CSS

0 comments
I've been working on a lot of lately on web design in various capacities. One problem I wanted to solve once and for all was centering #div tags either horizontally, vertically or both. Obviously this is a simple enough problem and I'm sure most of you can quickly align horizontally without a headache but vertical sometimes needs some extra considerations.

Our approach to this will use only CSS and proves to be quite readable later on.

Horizontal alignment

.cssClass
{
    margin: 0 auto;
    width: 200px;
    height: 200px;
}

Well that was easy, we got our div in the middle by setting the margin on the left and right (with a single property) to be automatically determined. Because we specify what the width and height is,the browser can then compute how much area is left on both sides and then divide that in half.

Vertical alignment

To achieve the vertical alignment we must know in advance the dimensions of the div. Secondly, we set the positioning to be absolute in order to detach the div and have free roam with it. The div is moved horizontally to the center of the window first, but that won't cut it yet as the actual point which is centered is the top left corner. From there, because we know the div dimensions we can offset it to the left and up by half the width and height which centers the actual center in the window center. The only special case here is when the div cannot have a side which is am even number, but we leave that up to the reader to sort out as necessary.

.cssClass
{
    width: 300px;
    height: 200px;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -100px 0 0 -150px;
}

Wednesday, May 19, 2010

Create radius based circle on Bing maps

0 comments

I've been working with Microsoft Virtual Earth as of lately. One of the requirements for my project has been to create geofence areas based on some latitude longitude which extends out on the map with a given radius. We then use these regions as entry/exit points for moving entities on the map, hence calling them geofences.

From the picture above, you can see that a geofence has a centroid which is a distinct LatLong object, how this is defined is up to you. In my example I found the coordinate tuple by allowing the user to geocode or reverse geocode, your mileage may vary in how you need to do this. The simplest example I could think of would be the Click event on the VEMap class whereby you simply extract the LatLong by the pixel coordinates.

So let's assume we have that LatLong object already. The following method will then define a ring around that point with a given radius in either miles or KM according to the radius of the Earth in either KM or miles.

public static Shape CreateCircle(LatLong Location, double Radius, double EarthRadius)

    {
        double lat = Utilities.ToRadians((double)Location.Latitude);
        double lon = Utilities.ToRadians((double)Location.Longitude);
        double angularDistance = Radius / EarthRadius;

        List points = new List();
        for (int i = 360; i > 0; i--)
        {
            double d = Utilities.ToRadians((double)i);
            double latRadians = Math.Asin(Math.Sin(lat) * Math.Cos(angularDistance) + Math.Cos(lat) * Math.Sin(angularDistance) * Math.Cos(d));
            double lonRadians = lon + Math.Atan2(Math.Sin(d) * Math.Sin(angularDistance) * Math.Cos(lat), Math.Cos(angularDistance) - Math.Sin(lat) * Math.Sin(latRadians));

            points.Add(new LatLong(Utilities.ToDegrees(latRadians), Utilities.ToDegrees(lonRadians)));
        }
        return new Shape(ShapeType.Polygon, points);
    }

From the Utilities class:

public static double EarthRadiusKM = 6367.0;

    public static double EarthRadiusMiles = 3956.0;

    public static double ToRadians(double d)
    {
        return d * (Math.PI / 180);
    }

    public static double ToDegrees(double r)
    {
        return r * 180 / Math.PI;
    }

The main thing to recognize in the first method is that we are creating the ring as a collection of 360 LatLong objects around the centroid. Points are defined in decreasing order such that the VEShape returned by the method can be converted easily to WKT to be stored in SQL using a geography data type. If we were to change the loop to start the index at 0 and count to 360, the ring of the Polygon would be invalid and subsequently rejected by SQL (first hand knowledge).

Finally, we can record in SQL this new geofence by calling a stored procedure "AddGeofence" which I've defined to accept the set of converted points as WKT.


public static string AddGeofence(Shape Geofence, string ClientID, string Creator)
    {
        DbCommand command = GenericDataAccess.CreateCommand();
        command.CommandText = "AddGeofence";

        DbParameter param = command.CreateParameter();
        param.ParameterName = "@ClientID";
        param.Value = ClientID;
        param.DbType = DbType.Int32;
        command.Parameters.Add(param);

        param = command.CreateParameter();
        param.ParameterName = "@Name";
        param.Value = Geofence.Title;
        param.DbType = DbType.String;
        param.Size = 250;
        command.Parameters.Add(param);

        param = command.CreateParameter();
        param.ParameterName = "@Description";
        param.Value = Geofence.Description;
        param.DbType = DbType.String;
        param.Size = 250;
        command.Parameters.Add(param);

        param = command.CreateParameter();
        param.ParameterName = "@Geofence";
        param.Value = GeofenceFunctions.ShapeToWKT(Geofence);
        param.DbType = DbType.String;
        command.Parameters.Add(param);

        return GenericDataAccess.ExecuteScalar(command);
    }

And finally in order to convert the ring to the WKT:

public static string ShapeToWKT(Shape shape)
    {
        string wkt = "";

        switch (shape.Type)
        {
            case ShapeType.Pushpin:
                wkt = PushpinToWKT(shape.Points);
                break;
            case ShapeType.Polyline:
                wkt = PolylineToWKT(shape.Points);
                break;
            case ShapeType.Polygon:
                wkt = PolygonToWKT(shape.Points);
                break;
            default:
                break;
        }
        return wkt;
    }

    private static string PolygonToWKT(List points)
    {
        string wkt = "POLYGON((";

        for (int i = 0; i < points.Count; i++)
        {
            wkt += points[i].Longitude.ToString();
            wkt += " ";
            wkt += points[i].Latitude.ToString();

            if (i < points.Count - 1) wkt += ",";
        }
        wkt += "))";

        return wkt;
    }

Wednesday, April 7, 2010

Self Organizing Map (Kohonen Network)

0 comments
Well its about time I shared something new with everyone. My latest and greatest is an implementation of Kohonen networks or otherwise known as the self organizing map. In this software package I've implemented this network for two tasks using the same algorithm to show the diversity which it can easily manage.

Download

In the image to the left, you'll see the resulting behavior of the self organizing map tasked with organizing RGB color values. While this is simply a toy problem, it does however serve as a great introduction to the topic.

Secondly (and why the download is so large) I've used the SOM for image clustering. Here I've taken statistical measures of image data sets to abstract away the dependence on the actual dimensions of the images and ensure focus is kept on the information itself. The result is the algorithm being capable of clustering images very accurately. I've included two data sets for you to try, the first of which is a set of cars I found by searching Google's image search and secondly a very large data set of web icons I've used very often in my projects. The result (if set large enough) is a really cool wallpaper all done with AI.

It's coolness in action. Hope you all enjoy.