Monday, April 8, 2013

foreach is pass by reference

To find out foreach iteration is pass by reference or pass by value, I wrote the test code as following:
        private static void test()
        {
            List<DataRecord> strlist = new List<DataRecord>(10);
            for (int i = 0; i < 10; i++)
                strlist.Add(new DataRecord(new String[] { }));
            int k=0;
            foreach (DataRecord r in strlist)
            {
                r["test"] = k++;
            }
            foreach (DataRecord r in strlist)
                Debug.Write(r["test"] + " ");
        }
And the result is:
 0 1 2 3 4 5 6 7 8 9 
So the conclusion is that foreeach iteration is pass by reference. Another interesting point is that if use something like foreach(string s in strlist), you cannot change the value of the string

Friday, April 5, 2013

Speed test: buffer then cut vs. intersection.buffer then cut

It's a case by case result. If the cutting geometry doesn't have a lot of points (STNumPoints), buffer then cut is faster, as shown below:
                      
         private static void test()
        {
            SqlGeometry poly = SqlGeometry.STGeomFromText(new SqlChars("POLYGON((-4 1, -4 -1, 4 -1, 4 1, -4 1))"), 4269),
                ln1 = SqlGeometry.STGeomFromText(new SqlChars("LINESTRING(-4 0, 4 0)"), 4269),
                ln2 = SqlGeometry.STGeomFromText(new SqlChars("LINESTRING(0 2, 0 -2)"), 4269);
            Stopwatch t1 = new Stopwatch(), t2 = new Stopwatch(), t3 = new Stopwatch(),t4=new Stopwatch();
            for (int i = 0; i < 100; i++)
            {
                t1.Start();
                poly.STDifference(ln2.STBuffer(0.00001));
                t1.Stop();
                t2.Start();
                poly.STDifference(poly.STIntersection(ln2).STBuffer(0.00001));
                t2.Stop();
                t3.Start();
                ln1.STDifference(ln2.STBuffer(0.00001));
                t3.Stop();
                t4.Start();
                ln1.STDifference(ln1.STIntersection(ln2).STBuffer(0.00001));
                t4.Stop();
            }
            Debug.WriteLine("t1=" + TimeSpan.FromMilliseconds(t1.ElapsedMilliseconds));
            Debug.WriteLine("t2=" + TimeSpan.FromMilliseconds(t2.ElapsedMilliseconds));
            Debug.WriteLine("t3=" + TimeSpan.FromMilliseconds(t3.ElapsedMilliseconds));
            Debug.WriteLine("t4=" + TimeSpan.FromMilliseconds(t4.ElapsedMilliseconds));
        }
[result]
t1=00:00:00.0280000
t2=00:00:00.0310000
t3=00:00:00.0250000
t4=00:00:00.0980000

If the cutting geometry has a lot of points, intersection.buffer then cut is faster, as shown below:
        private static void test()
        {
            StringBuilder sb = new StringBuilder("LINESTRING(");            
            for (int i = -1000; i < 1000; i++)
            {
                sb.Append(i + " 0");
                if (i != 999)
                    sb.Append(",");
                else
                    sb.Append(")");
            }

            SqlGeometry poly = SqlGeometry.STGeomFromText(new SqlChars("POLYGON((-4 1, -4 -1, 4 -1, 4 1, -4 1))"), 4269),
                ln1 = SqlGeometry.STGeomFromText(new SqlChars("LINESTRING(-4 0, 4 0)"), 4269),
                ln2 = SqlGeometry.STGeomFromText(new SqlChars(sb.ToString()), 4269);
            Stopwatch t1 = new Stopwatch(), t2 = new Stopwatch(), t3 = new Stopwatch(),t4=new Stopwatch();
            for (int i = 0; i < 100; i++)
            {
                t1.Start();
                poly.STDifference(ln2.STBuffer(0.00001));
                t1.Stop();
                t2.Start();
                poly.STDifference(poly.STIntersection(ln2).STBuffer(0.00001));
                t2.Stop();
                t3.Start();
                ln1.STDifference(ln2.STBuffer(0.00001));
                t3.Stop();
                t4.Start();
                ln1.STDifference(ln1.STIntersection(ln2).STBuffer(0.00001));
                t4.Stop();
            }
            Debug.WriteLine("t1=" + TimeSpan.FromMilliseconds(t1.ElapsedMilliseconds));
            Debug.WriteLine("t2=" + TimeSpan.FromMilliseconds(t2.ElapsedMilliseconds));
            Debug.WriteLine("t3=" + TimeSpan.FromMilliseconds(t3.ElapsedMilliseconds));
            Debug.WriteLine("t4=" + TimeSpan.FromMilliseconds(t4.ElapsedMilliseconds));
        }
[result]
t1=00:00:01.3610000
t2=00:00:00.0770000
t3=00:00:01.3190000
t4=00:00:00.0510000

Thursday, April 4, 2013

Be Aware: Sqlite uses a dynamic data type system


For additional information, sqlite3 uses a dynamic data type system. so anything past these:
  • NULL
  • INTEGER
  • REAL
  • TEXT
  • BLOB
are just hints to sqlite (technically, affinity), and it'll end up deciding on its own what type it is or is not.
the functions that return doubles, ints, etc are part of the sqlite C API try its best to give you what you want.... so what's stored in a column can potentially be converted by sqlite if what you're asking for is different from what's in the db.
about midway down, there's a handy table that'll let you know what to expect.

Monday, April 1, 2013

Union on two normal geometries could cause exception of invalid geometry

set @a = geometry::STGeomFromText('POLYGON ((-82.169222373340745 36.313505017518764, -82.1689948301937 36.313636231730925, -82.169144694926217 36.313896117397235, -82.169118706369773 36.313911103876308, -82.169136897806311 36.313934959107428, -82.168898345553316 36.314116873414605, -82.168906538223382 36.314127616860787, -82.169145090476377 36.31394570255361, -82.169163281912915 36.313969557770179, -82.169180794822751 36.313993915478932, -82.16893721773522 36.314169044577284, -82.168944722216111 36.314179482113104, -82.169188299303642 36.314004353014752, -82.169205812213477 36.314028710723505, -82.16922261781292 36.314053561727633, -82.168974107858958 36.314221617678413, -82.168982719915221 36.31423435259785, -82.169231229840079 36.31406629664707, -82.169248035439523 36.314091147636645, -82.169264097610721 36.314116485489649, -82.169010719168 36.314277107259841, -82.169018743181368 36.314289765025023, -82.1692721216532 36.31412914324028, -82.169288183824392 36.314154481093283, -82.169303491538884 36.314180281754275, -82.169045484974049 36.314333358881413, -82.16905147532816 36.314343455422204, -82.169309481889215 36.314190378297312, -82.1693247896037 36.314216178958304, -82.169354020094033 36.314268577232724, -82.169435400719522 36.3144245105068, -82.169937897386262 36.314055754584842, -82.16939822662971 36.313749916720553, -82.169380749954144 36.31375999476586, -82.1693754500593 36.3137530447857, -82.169368469505571 36.313758367992705, -82.169222373340745 36.313505017518764))',4269);
set @b = geometry::STGeomFromText('POLYGON ((-82.1690774135017 36.3143885305297, -82.1690774135047 36.314388530535,-82.169601396196 36.3140962256613,-82.169601396196 36.3140962256613,-82.1690774135017 36.3143885305297))',4269);

The first polygon looks like
clip_image002
The second polygon looks like
clip_image004
If conducting the union operation:

Select @a.STUnion(@b);

Here is the error message:

A .NET Framework error occurred during execution of user-defined routine or aggregate "geometry":
System.ArgumentException: 24144: This operation cannot be completed because the instance is not valid. Use MakeValid to convert the instance to a valid instance. Note that MakeValid may cause the points of a geometry instance to shift slightly.
System.ArgumentException:
   at Microsoft.SqlServer.Types.SqlGeometry.ThrowIfInvalid()
   at Microsoft.SqlServer.Types.SqlGeometry.STUnion(SqlGeometry other)

Friday, March 29, 2013

c#: Get all the files in a folder

Get all the files in a folder
private static List files = new List();
static void FullDirList(DirectoryInfo dir, string searchPattern)
{
 // Console.WriteLine("Directory {0}", dir.FullName);
 // list the files
 try
 {
  foreach (FileInfo f in dir.GetFiles(searchPattern))
  {
   //Console.WriteLine("File {0}", f.FullName);
   files.Add(f);
  }
 }
 catch
 {
  Console.WriteLine("Directory {0}  \n could not be accessed!!!!", dir.FullName);
  return;  // We alredy got an error trying to access dir so dont try to access it again
 }

 // process each directory
 // If I have been able to see the files in the directory I should also be able 
 // to look at its directories so I dont think I should place this in a try catch block
 foreach (DirectoryInfo d in dir.GetDirectories())
 {                
  FullDirList(d, searchPattern);
 }

}

USGS DEM trivials


  • Get the correct folder name

     
string foldername = (lat > 0 ? "n" + Math.Ceiling(lat).ToString("00") : "s" + Math.Ceiling(lat * -1).ToString("00")) + (lon > 0 ? "e" + Math.Ceiling(lon).ToString("000") : "w" + Math.Ceiling(lon * -1).ToString("000"));

  • Does each DEM data has the same cell size? No. The scanning result shows the following possibilities
              9.2592592593E-05
              9.2592592599959E-05
              9.2592592599958E-05

A good example demonstrate the accessor usage in C# (from MSDN)

In this example, two classes, Cube and Square, implement an abstract class, Shape, and override its abstract Area property. Note the use of the override modifier on the properties. The program accepts the side as an input and calculates the areas for the square and cube. It also accepts the area as an input and calculates the corresponding side for the square and cube.
// overridding_properties.cs
// Overriding properties
using System;
abstract class Shape 
{
   public abstract double Area 
   {
      get;
      set;
   }
}

class Square: Shape 
{
      public double side;

      // Constructor:
      public Square(double s) 
      {
         side = s;
      }

   // The Area property
   public override double Area 
   {
      get 
      {
         return side*side ; 
      }
      set 
      {
         // Given the area, compute the side
         side = Math.Sqrt(value); 
      }
   }
}

class Cube: Shape 
{
      public double side;    

      // Constructor:
      public Cube(double s) 
      {
         side = s;
      }

      // The Area property
      public override double Area 
      {
         get 
         {
            return 6*side*side;
         }
         set 
         {
            // Given the area, compute the side
            side = Math.Sqrt(value/6);
         }
      }
}

public class MainClass 
{
   public static void Main()  
   {
      // Input the side:
      Console.Write("Enter the side: ");
      string sideString = Console.ReadLine();   
      double side = double.Parse(sideString);

      // Compute areas:
      Square s = new Square(side);
      Cube c = new Cube(side);

      // Display results:
      Console.WriteLine("Area of a square = {0:F2}",s.Area);
      Console.WriteLine("Area of a cube = {0:F2}", c.Area); 

      // Input the area:
      Console.Write("Enter the area: ");
      string areaString = Console.ReadLine();   
      double area = double.Parse(areaString);

      // Compute sides:
      s.Area = area;
      c.Area = area;

      // Display results:
      Console.WriteLine("Side of a square = {0:F2}", s.side);
      Console.WriteLine("Side of a cube = {0:F2}", c.side);
   }
}