using System; using System.IO; using Microsoft.SqlServer.Server; using Microsoft.SqlServer.Types; /* * I make no claim of copyright ownership of all the code listed below - the original authors of each code * are idenfied * * Place this file in C:\assemblies, then compile it to C:\assemblies\Aggregate.dll * via the Command Prompt using this command (you may need to modify for your environment) c:\windows\microsoft.net\framework\v3.5\csc /t:library /r:Microsoft.SqlServer.Types.dll C:\assemblies\aggregate.cs * Then in SQL Server 2008 (Katmai) Management Studio run these commands CREATE ASSEMBLY SpatialAggregate FROM 'c:\assemblies\Aggregate.dll' go CREATE AGGREGATE EnvelopeAggregate(@input GEOMETRY) RETURNS GEOMETRY external name [SpatialAggregate].[SilverlightEarth.Geoquery.SqlClr.EnvelopeAggregate] go CREATE AGGREGATE UnionAggregate(@input GEOMETRY) RETURNS GEOMETRY external name [SpatialAggregate].[SilverlightEarth.Geoquery.SqlClr.UnionAggregate] go sp_configure 'clr enabled', 1; go RECONFIGURE; go */ namespace SilverlightEarth.Geoquery.SqlClr { /// /// /// /// /// Author: Steven Hemingray /// Source: MSDN Forums /// Link: http://forums.microsoft.com/TechNet/ShowPost.aspx?PostID=2527689&SiteID=17 /// [Serializable] [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.Native)] public struct EnvelopeAggregate { public double minX; public double minY; public double maxX; public double maxY; public void Init() { minX = double.MaxValue; minY = double.MaxValue; maxX = double.MinValue; maxY = double.MinValue; } public void Accumulate(SqlGeometry value) { if (value != null && !value.IsNull && !value.STIsEmpty()) { SqlGeometry envelope = value.STEnvelope(); if (envelope.STPointN(1).STX.Value < minX) minX = envelope.STPointN(1).STX.Value; if (envelope.STPointN(1).STY.Value < minY) minY = envelope.STPointN(1).STY.Value; if (envelope.STPointN(3).STX.Value > maxX) maxX = envelope.STPointN(3).STX.Value; if (envelope.STPointN(3).STY.Value > maxY) maxY = envelope.STPointN(3).STY.Value; } } public void Merge(EnvelopeAggregate group) { if (group.minX < minX) minX = group.minX; if (group.minY < minY) minY = group.minY; if (group.maxX > maxX) maxX = group.maxX; if (group.maxY > maxY) maxY = group.maxY; } public SqlGeometry Terminate() { if (minX == double.MaxValue) //All inputs were null or empty return SqlGeometry.Null; return SqlGeometry.Parse(String.Format("POLYGON (({0} {1}, {2} {1}, {2} {3}, {0} {3}, {0} {1}))", minX, minY, maxX, maxY)); } } // EnvelopeAggregate /// /// /// /// /// Author: Steven Hemingray /// Source: MSDN Forums /// Link: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2508004&SiteID=1 /// [Serializable] [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = -1)] public struct UnionAggregate : IBinarySerialize { public SqlGeometry union; public void Init() { union = new SqlGeometry(); } public void Accumulate(SqlGeometry value) { if (union.IsNull || union.STIsEmpty()) union = value; else union = union.STUnion(value); } public void Merge(UnionAggregate group) { if (union.IsNull || union.STIsEmpty()) union = group.union; else union = union.STUnion(group.union); } public SqlGeometry Terminate() { return union; } public void Read(BinaryReader r) { union = new SqlGeometry(); union.Read(r); } public void Write(BinaryWriter w) { union.Write(w); } } // UnionAggregate }