Skip to content

Archive

Tag: C#

Spirals are a relatively easy shape to draw, but in order to draw a good spiral we need a bit of simple trigonometry.

The basics of the spiral are the radius of a particular point from the origin, at a particular angle, and for the code below, the radius increases as the angle increases. The exact relation between angle and radius determines the type of spiral.

In the simplest case, the radius will increase linearly with the angle, thus
Radius = Angle * ScalingFactor

We can also use quadratic or cubic equations to define the realtionship
Radius = Angle2 * ScalingFactor
Radius = Angle3 * ScalingFactor

The most interesting spiral, however, is the exponential spiral, which is found in nature most famously in the nautilus shell.
Radius = Anglee * ScalingFactor

Now that you can determine the relationship between radius and angle, it is a simple matter to draw the spiral.

Starting at the origin, with angle 0, we need to increment the angle by a certain amount – in the code below by 0.5 degrees per iteration – and then calculate the radius, and then using the radius and the angle, we are able to calculate the x and y coordinates of the point by using simple trigonometry, since sin(angle) = y/r and cos(angle) = x/r.

Now after finding the coordinates of the point, we simply need to draw a line segment from our previous point to the new point. The smaller the angle increment, the smoother the curve which is drawn will be, but it also means that more points need to be calculated to draw the same curve, which consumes more processing time.

One good way of speeding up the calcution of the curve, is to use a lookup table for the cos and sin values instead of calculating them with each iteration, but that is a topic for another post.

      public void drawSpiral(double scale, double delta, double revolutions, int centreX, int centreY, SpiralType spiralType, int width, int height, Color color, Graphics g)
      {
         Pen p = new Pen(Color.Blue, 1);

         double prevX = centreX;
         double prevY = centreY;
         double X = centreX;
         double Y = centreY;
         double theta = 0;
         double radius = 0;

         while (theta <= (revolutions * 360))
         {
            theta += delta;
            if (spiralType == SpiralType.Linear)
            {
               radius = theta * scale;
            }
            else if (spiralType == SpiralType.Quadratic)
            {
               radius = theta * theta * scale;
            }
            else if (spiralType == SpiralType.Cubic)
            {
               radius = theta * theta * theta * scale;
            }
            else if (spiralType == SpiralType.Exponential)
            {
               radius = (Math.Pow(theta / 180 * Math.PI, Math.E)) * scale;
            }

            prevX = X;
            prevY = Y;
            X = (radius * Math.Cos(theta / 180 * Math.PI)) + centreX;
            Y = (radius * Math.Sin(theta / 180 * Math.PI)) + centreY;
            g.DrawLine(p, (float)prevX, (float)prevY, (float)X, (float)Y);
         }

      }

      public enum SpiralType
      {
         Linear,
         Quadratic,
         Cubic,
         Exponential
      }
Share

Way back in my earlier days of programming, I wrote a unit convertor that converted between different units such as distance and weights. It was a really ugly and inelegant solution, so I thought I would look at coming up with a new and improved version.

Unit conversions themselves are very easy to accomplish. All you need is a reference unit (which for this tutorial, we will use metres) and the conversion amount between the two units you are converting between and the reference unit.

So, to put that simpler, if you want to convert from millimetres to kilometres, you first convert the millimetres to metres, and then convert the metres value to kilometres in a two-part calculation.

The trick though is not the calculation itself, but rather managing the conversion rules.
continue reading…

Share

In C#, the char data type represents a text character. Internally though, this value is pretty much a numeric value.

Think here of Ascii or Unicode values. These codings essentially map a character to a particular numeric value, which is what the char data type stores.

One rather interesting side effect of this is that you can iterate through character values in exactly the same way as you would for an int or long.

In the sample code below, the code loops through all the capital letters of the alphabet, adding each letter to a string.

string alphabet = "";
for (char c = 'A'; c <= 'Z'; c++)
{
    alphabet += c.ToString();
}
Share

When using sorting with the ASP.NET gridview, the header cell of a column contains a link (generated internally by .NET using a LinkButton).

Everything else in the gridview is easily styled by readily accessable CssClass tags. This is not quite so easy to accomplish for the sort link in the header of a column.

To acheive this, we need to catch the RowCreated event and manually find the header we are looking for, by comparing the SortExpression of each column’s header link with the SortExpression of the gridview which gets set when you sort the gridview.

Once you have found the LinkButton associated with the column, it is an easy matter to set the class using the LinkButton‘s CssClass property.

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.Header)
    {
        foreach (TableCell tc in e.Row.Cells)
        {
            if (tc.HasControls())
            {
                LinkButton headerLink = (LinkButton)tc.Controls[0];
                if (GridView1.SortExpression == headerLink.CommandArgument)
                    headerLink.CssClass = "sorted";

                if (SortDirection == SortDirection.Descending)
                    headerLink.CssClass += " desc";
                else
                    headerLink.CssClass += " asc";
            }
        }
    }
}
Share

Now that we know how gedcom files work (covered in part 1), we need to actually parse the file.

The way in which the gedcom is structured is that each new record entry starts on a line with a 0. All lines with a 1 under that belong to that record. Similarly, lines with a 2 prefix, belond to the the entry prefixed by a 1 directly above it.

This makes processing rather straightforward. All we need to do, is read the file line by line, then split up the line into its components, and process accordingly.

All lines have a number (0, 1 or 2) as the first field in the line, and each field is seperated by a space, for example 1 SOUR FamilyTraces

The second field in the line is usually the keyword which tells us what the data represents. Some keywords will not need an extra data field in the third field, but usually, these types of lines which are grouped together with that line.
As an example, the VERS and FORM lines are linked to the GEDC keyword as the 2 in the first field shows they belong to the preceding line.

1 GEDC
2 VERS 5.5
2 FORM LINEAGE-LINKED

There is an exception to the second field being the keyword, and that is in the individual, family and note record entry fields which take the format 0 @[email protected] INDI for an individual record for example.

Based on all of that, all we need to do, is split up the line into the three fields, and then process each keyword independantly from each other, while keeping track of which type of record we are currently in, so that we can assign the data to the correct structure.

Here is the full code for the parser, that works pretty much exactly as described above. I have not implemented the full spec of the gedcom file format, but only enough as I need for the application. It is easily modified, however, to add the rest of the spec in if needed.

Usually, now would be the time where I list the source code for the code I have talked about in this blog post, but due to some bug with WordPress and the plug-in I am using to render my code samples nicely, the code for this section is crashing Firefox, so I have included the code for the GedcomParser class as a link to a text file containing the code.

Share

In my previous post in this series, I introduced the Family Traces family tree application. Now, I am going to go through the importing of a gedcom file.

Firstly, what is a gedcom file?

The gedcom file format is a text file format for the transmission and storage of genealogical data, created by the Church of the Latter Day Saints for their genealogical projects.

A standard gedcom file has a header section, individual records, family records and notes. The various records are linked to each other by ids, in the format of @[email protected] for an individual record for example. For a full spec of the gedcom format, have a look here.

Here is a sample gedcom file

0 HEAD
1 SOUR FamilyTraces
2 NAME Family Traces
2 CORP Serge Meunier
1 DEST Standard GEDCOM
1 DATE 2010/02/16
1 CHAR ANSEL
1 GEDC
2 VERS 5.5
2 FORM LINEAGE-LINKED
0 @[email protected] INDI
1 John/Smith/
2 GIVN John
2 SURN Smith
1 SEX M
1 BIRT
2 DATE 15 dec 1950
2 PLAC
1 FAMC @[email protected]
1 FAMS @[email protected]
0 @[email protected] INDI
1 Jane/Doe/
2 GIVN Jane
2 SURN Doe
1 SEX F
1 FAMC @[email protected]
0 @[email protected] FAM
1 HUSB @[email protected]
1 WIFE @[email protected]
1 CHIL @[email protected]
0 TRLR

Before we start processing the file, we need to have some data structures to hold the data from the file.

    public struct GedcomHeader
    {
        public string Source;
        public string SourceVersion;
        public string SourceName;
        public string SourceCorporation;
        public string Destination;
        public string Date;
        public string File;
        public string CharacterEncoding;
        public string GedcomVersion;
        public string GedcomForm;
    }

    public struct GedcomIndividual
    {
        public string Id;
        public string GivenName;
        public string Surname;
        public string Suffix;
        public string Sex;
        public string BirthDate;
        public string BirthPlace;
        public string Occupation;
        public string Description;
        public string Nationality;
        public string DiedDate;
        public string DiedPlace;
        public string DiedCause;
        public string ParentFamilyId;
        public string SpouseFamilyId;
        public ArrayList Notes;

        public GedcomIndividual(string id)
        {
            Id = id;
            GivenName = "";
            Surname = "";
            Suffix = "";
            Sex = "";
            BirthDate = "";
            BirthPlace = "";
            Occupation = "";
            Description = "";
            Nationality = "";
            DiedDate = "";
            DiedPlace = "";
            DiedCause = "";
            ParentFamilyId = "";
            SpouseFamilyId = "";
            Notes = new ArrayList();
        }
    }

    public struct GedcomFamily
    {
        public string Id;
        public string HusbandId;
        public string WifeId;
        public string MarriageDate;
        public string MarriagePlace;
        public ArrayList Children;
        public ArrayList Notes;

        public GedcomFamily(string id)
        {
            Id = id;
            HusbandId = "";
            WifeId = "";
            MarriageDate = "";
            MarriagePlace = "";
            Children = new ArrayList();
            Notes = new ArrayList();
        }
    }

    public struct GedcomNote
    {
        public string Id;
        public string Text;

        public GedcomNote(string id)
        {
            Id = id;
            Text = "";
        }
    }

We also need a set of enumerations we will use to keep track of where we are in the file. This is important because the meaning of a field in the file is dependant on the place in the file it occurs, so we need to be aware of what we need to do at all times, but more on that later.

    public enum GedcomRecordEnum
    {
        None,
        Header,
        Individual,
        Family,
        Note
    }

    public enum GedcomSubRecordEnum
    {
        None,
        HeaderSource,
        HeaderGedcom,
        IndividualName,
        IndividualBirth,
        IndividualDeath,
        FamilyChildren,
        FamilyMarriage
    }

The full source is available Here.
Now we need to get to parsing the file, which is covered in Importing a Gedcom file – Part 2

Share

I love being able to trace my family tree, and have used several good genealogy applications which I have found very useful, including Family Tree Legends and Family Tree Builder. The problem I have though, is that they do not always contain everything which I am looking for, so I decided to write a family tree application to plug in the holes.

Family Traces, which you can download the full source for Here, is a fully functional, albeit bare-boned family tree application, which can import and export Gedcom files, calculate ancestors and descendants, and allow you to edit the family tree. Everything is there for a starting point, from where you can develop further reports and functionality.

All of that will come in later posts in this series though. For now, I am going to focus on the core of the application – the data layout. This layout is created within an Access database included with the application.

The two main components of any family tree are individuals and families.

Starting with the individual, each person in the family tree will have a record in the database. The most important data we need for an individual are:

* Individual Id
* Name
* Birth date
* Birth place
* Death date
* Death place

These fields are vital in determining if the person we are looking at is the same person listed in genealogical records, such as birth certificates, genealogical lists etc.

Now data collection for an individual is not restricted to these fields, and you are free to create as many fields as your want for things like physical attributes, cause of death, photos and general notes.

Moving onto families now, a family is what connects different individuals together into a tree.

The main family record will have

* Family Id
* Husband Id
* Wife Id
* Marriage date
* Marriage place

This links the husband and wife individual records into the family, and allows you to track the marriage date and place, which is also important in genealogical research, as it may provide crucial hints to the individuals, particularly if the birth and death dates of the individuals are unsure.

The last thing we need is to be able to link individuals as children within a family, and this is done using a separate table, which keeps track of the family id, as well as the individual id of the child, and each family can have multiple individuals attached to it as children.

In the database setup for the application, I also included a field in the individual record for the parent family record, which makes it easier to link the individual to a family as a child when processing the tree. This means that we are able to find the family that the individual is a child of without having to check the family records directly.

Now that is all there is to the core of a genealogy application, so feel free to play around with the application, and I will explain more about how the gedcom file format works in the next tutorial…

Share