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
}