public override Envelope GetExtents() { if (_cachedExtents != null) return new Envelope(_cachedExtents); Envelope box = null; if (_spatiaLiteIndex == SpatiaLiteIndex.RTree) { using (var conn = new SQLiteConnection(ConnectionString)) { conn.Open(); var strSQL = string.Format("SELECT \"data\" FROM \"idx_{0}_{1}_node\" WHERE \"nodeno\"=1;", _table, _geometryColumn); using (var cmd = conn.CreateCommand()) { cmd.CommandText = strSQL; var result = cmd.ExecuteScalar(); if (result != null && result != DBNull.Value) { var buffer = (byte[]) result; var node = new RTreeNode(buffer); _cachedExtents = float.IsNaN(node.XMin) ? new Envelope() : new Envelope(node.XMin, node.XMax, node.YMin, node.YMax); return new Envelope(_cachedExtents); //var entities = new float[2*_numOrdinateDimensions]; //var offset = 12; //for (var i = 0; i < 2*_numOrdinateDimensions; i++) //{ // Array.Reverse(buffer, offset, 4); // entities[i] = BitConverter.ToSingle(buffer, offset); // offset += 4; //} //return new Envelope(entities[0], entities[2], entities[1], entities[3]); } throw new Exception(); } } } using (SQLiteConnection conn = SpatiaLiteConnection(ConnectionString)) { //string strSQL = "SELECT Min(minx) AS MinX, Min(miny) AS MinY, Max(maxx) AS MaxX, Max(maxy) AS MaxY FROM " + this.Table; string strSQL; if (_spatiaLiteIndex == SpatiaLiteIndex.RTree && String.IsNullOrEmpty(_definitionQuery)) { strSQL = string.Format( "SELECT MIN(xmin) AS minx, MAX(xmax) AS maxx, MIN(ymin) AS miny, MAX(ymax) AS maxy from {0};", string.Format("idx_{0}_{1}", _table, _geometryColumn)); } else { strSQL = string.Format( "SELECT MIN(MbrMinX({0})) AS minx, MIN(MbrMinY({0})) AS miny, MAX(MbrMaxX({0})) AS maxx, MAX(MbrMaxY({0})) AS maxy FROM {1};", _geometryColumn, FromClause(_table)); } using (var command = new SQLiteCommand(strSQL, conn)) { using (var dr = command.ExecuteReader()) if (dr.Read()) { if (dr.IsDBNull(0)) return new Envelope(0,0,0,0); box = new Envelope( (double) dr["minx"], (double) dr["maxx"], (double) dr["miny"], (double) dr["maxy"]); } conn.Close(); } _cachedExtents = box; return new Envelope(box); } }
public override Envelope GetExtents() { if (_cachedExtents != null) { return(new Envelope(_cachedExtents)); } Envelope box = null; if (_spatiaLiteIndex == SpatiaLiteIndex.RTree) { using (var conn = GetConnection(ConnectionString)) { var strSQL = string.Format("SELECT \"data\" FROM \"idx_{0}_{1}_node\" WHERE \"nodeno\"=1;", _table, _geometryColumn); using (var cmd = conn.CreateCommand()) { cmd.CommandText = strSQL; var result = cmd.ExecuteScalar(); if (result != null && result != DBNull.Value) { var buffer = (byte[])result; var node = new RTreeNode(buffer); _cachedExtents = float.IsNaN(node.XMin) ? new Envelope() : new Envelope(node.XMin, node.XMax, node.YMin, node.YMax); return(new Envelope(_cachedExtents)); } throw new Exception(); } } } using (var conn = GetConnection(ConnectionString)) { var strSQL = string.Format("SELECT \"{1}\" AS \"_smtmp_\" FROM \"{0}\"", _table, _geometryColumn); using (var command = new SQLiteCommand(strSQL, conn)) { using (var dr = command.ExecuteReader()) { if (dr.HasRows) { double minx = double.MaxValue, miny = double.MaxValue, maxx = double.MinValue, maxy = double.MinValue; var geoReader = new GaiaGeoReader(Factory.CoordinateSequenceFactory, Factory.PrecisionModel, _ordinates); while (dr.Read()) { var geom = geoReader.Read((byte[])dr.GetValue(0)); var env = geom.EnvelopeInternal; if (minx > env.MinX) { minx = env.MinX; } if (miny > env.MinY) { miny = env.MinY; } if (maxx < env.MaxX) { maxx = env.MaxX; } if (maxy < env.MaxY) { maxy = env.MaxY; } box = new Envelope(minx, maxx, miny, maxy); } dr.Close(); } else { box = new Envelope(); } } conn.Close(); } _cachedExtents = box; return(new Envelope(box)); } }
public override Envelope GetExtents() { if (_cachedExtents != null) return new Envelope(_cachedExtents); Envelope box = null; if (_spatiaLiteIndex == SpatiaLiteIndex.RTree) { using (var conn = GetConnection(ConnectionString)) { var strSQL = string.Format("SELECT \"data\" FROM \"idx_{0}_{1}_node\" WHERE \"nodeno\"=1;", _table, _geometryColumn); using (var cmd = conn.CreateCommand()) { cmd.CommandText = strSQL; var result = cmd.ExecuteScalar(); if (result != null && result != DBNull.Value) { var buffer = (byte[])result; var node = new RTreeNode(buffer); _cachedExtents = float.IsNaN(node.XMin) ? new Envelope() : new Envelope(node.XMin, node.XMax, node.YMin, node.YMax); return new Envelope(_cachedExtents); } throw new Exception(); } } } using (var conn = GetConnection(ConnectionString)) { var strSQL = string.Format("SELECT \"{1}\" AS \"_smtmp_\" FROM \"{0}\"", _table, _geometryColumn); using (var command = new SQLiteCommand(strSQL, conn)) { using (var dr = command.ExecuteReader()) { if (dr.HasRows) { double minx = double.MaxValue, miny = double.MaxValue, maxx = double.MinValue, maxy = double.MinValue; var geoReader = new GaiaGeoReader(Factory.CoordinateSequenceFactory, Factory.PrecisionModel, _ordinates); while (dr.Read()) { var geom = geoReader.Read((byte[]) dr.GetValue(0)); var env = geom.EnvelopeInternal; if (minx > env.MinX) minx = env.MinX; if (miny > env.MinY) miny = env.MinY; if (maxx < env.MaxX) maxx = env.MaxX; if (maxy < env.MaxY) maxy = env.MaxY; box = new Envelope(minx, maxx, miny, maxy); } } else { box = new Envelope(); } dr.Close(); } } conn.Close(); _cachedExtents = box; return new Envelope(box); } }
/// <summary> /// Splits a node into two nodes. /// </summary> /// <param name="overflownNode">The overflown node.</param> /// <param name="firstNode">The first produced node.</param> /// <param name="secondNode">The second produced node.</param> protected override void SplitNode(RTreeNode overflownNode, out RTreeNode firstNode, out RTreeNode secondNode) { List <RTreeNode> alongChosenAxis = ChooseSplitAxis(overflownNode); Int32 minIndex = MinChildren; Double minOverlap = ComputeOverlap(Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, MinChildren).Select(x => x.Envelope)), Envelope.FromEnvelopes(alongChosenAxis.GetRange(MinChildren, alongChosenAxis.Count - MinChildren).Select(x => x.Envelope))); // ChooseSplitIndex for (Int32 i = MinChildren + 1; i <= MaxChildren - MinChildren + 1; i++) { Double actOverlap = ComputeOverlap(Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, i).Select(x => x.Envelope)), Envelope.FromEnvelopes(alongChosenAxis.GetRange(i, alongChosenAxis.Count - i).Select(x => x.Envelope))); if (minOverlap > actOverlap) { minOverlap = actOverlap; minIndex = i; } else if (minOverlap == actOverlap) { Double minArea = Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, minIndex).Select(x => x.Envelope)).Surface + Envelope.FromEnvelopes(alongChosenAxis.GetRange(minIndex, alongChosenAxis.Count - minIndex).Select(x => x.Envelope)).Surface; Double actArea = Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, i).Select(x => x.Envelope)).Surface + Envelope.FromEnvelopes(alongChosenAxis.GetRange(i, alongChosenAxis.Count - i).Select(x => x.Envelope)).Surface; if (minArea > actArea) { minIndex = i; } } } firstNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren); secondNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren); foreach (RTreeNode node in alongChosenAxis.GetRange(0, minIndex)) { firstNode.AddChild(node); } foreach (RTreeNode node in alongChosenAxis.GetRange(minIndex, alongChosenAxis.Count - minIndex)) { secondNode.AddChild(node); } }
internal RTreeNode(int maxKeysPerNode, RTreeNode parent) { Parent = parent; Children = new List <RTreeNode>(); }
/// <summary> /// Chooses seed elements for splitting a node using the linear cost algorithm. /// </summary> /// <param name="nodes">The nodes contained by the overflown node.</param> /// <param name="firstNode">The first seed node.</param> /// <param name="secondNode">The second seed node.</param> protected virtual void PickSeeds(IList <RTreeNode> nodes, out RTreeNode firstNode, out RTreeNode secondNode) { // the linear cost algorithm chooses the two points which are // the furthest away from each other considering the three axis RTreeNode highestLowX = nodes[0]; RTreeNode highestLowY = nodes[0]; RTreeNode highestLowZ = nodes[0]; for (Int32 i = 1; i < nodes.Count; i++) { if (highestLowX.Envelope.MinX < nodes[i].Envelope.MinX) { highestLowX = nodes[i]; } if (highestLowY.Envelope.MinY < nodes[i].Envelope.MinY) { highestLowY = nodes[i]; } if (highestLowZ.Envelope.MinZ < nodes[i].Envelope.MinZ) { highestLowZ = nodes[i]; } } RTreeNode lowestHighX = nodes.FirstOrDefault(x => x != highestLowX); RTreeNode lowestHighY = nodes.FirstOrDefault(x => x != highestLowY); RTreeNode lowestHighZ = nodes.FirstOrDefault(x => x != highestLowZ); Double minX, minY, minZ; minX = minY = minZ = Double.MaxValue; Double maxX, maxY, maxZ; maxX = maxY = maxZ = Double.MinValue; foreach (RTreeNode node in nodes) { if (node.Envelope.MaxX < lowestHighX.Envelope.MaxX && node != highestLowX) { lowestHighX = node; } if (node.Envelope.MaxY < lowestHighY.Envelope.MaxY && node != highestLowY) { lowestHighY = node; } if (node.Envelope.MaxZ < lowestHighZ.Envelope.MaxZ && node != highestLowZ) { lowestHighZ = node; } if (node.Envelope.MinX < minX) { minX = node.Envelope.MinX; } if (node.Envelope.MaxX > maxX) { maxX = node.Envelope.MaxX; } if (node.Envelope.MinY < minY) { minY = node.Envelope.MinY; } if (node.Envelope.MaxY > maxY) { maxY = node.Envelope.MaxY; } if (node.Envelope.MinZ < minZ) { minZ = node.Envelope.MinZ; } if (node.Envelope.MaxZ > maxZ) { maxZ = node.Envelope.MaxZ; } } Double normalizedDistanceX = (highestLowX.Envelope.MinX - lowestHighX.Envelope.MaxX) / (maxX - minX); Double normalizedDistanceY = (highestLowY.Envelope.MinY - lowestHighY.Envelope.MaxY) / (maxY - minY); if (normalizedDistanceX >= normalizedDistanceY) { firstNode = lowestHighX; secondNode = highestLowX; } else { firstNode = lowestHighY; secondNode = highestLowY; } if (!lowestHighZ.Envelope.IsPlanar || !highestLowZ.Envelope.IsPlanar) { Double normalizedDistanceZ = (highestLowZ.Envelope.MinZ - lowestHighZ.Envelope.MaxZ) / (maxZ - minZ); if ((firstNode == lowestHighX && normalizedDistanceZ > normalizedDistanceX) || (firstNode == lowestHighY && normalizedDistanceZ > normalizedDistanceX)) { firstNode = lowestHighZ; secondNode = highestLowZ; } } }
/// <summary> /// Adds a node into the tree on a specified height. /// </summary> /// <param name="node">The node.</param> /// <param name="height">The height where the node should be inserted.</param> protected override void AddNode(RTreeNode node, Int32 height = -1) { _visitedLevels = new Boolean[Height]; InsertInSpecifiedHeight(node, height, height); }
/// <summary> /// Splits a node into two nodes. /// </summary> /// <param name="overflownNode">The overflown node.</param> /// <param name="firstNode">The first produced node.</param> /// <param name="secondNode">The second produced node.</param> protected virtual void SplitNode(RTreeNode overflownNode, out RTreeNode firstNode, out RTreeNode secondNode) { RTreeNode firstSeed, secondSeed; PickSeeds(overflownNode.Children, out firstSeed, out secondSeed); firstNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren); secondNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren); firstNode.AddChild(firstSeed); secondNode.AddChild(secondSeed); overflownNode.Children.Remove(firstSeed); overflownNode.Children.Remove(secondSeed); while (overflownNode.ChildrenCount > 0) { RTreeNode node = PickNext(overflownNode.Children); if (firstNode.ChildrenCount + overflownNode.ChildrenCount <= MinChildren) { firstNode.AddChild(node); } else if (secondNode.ChildrenCount + overflownNode.ChildrenCount <= MinChildren) { secondNode.AddChild(node); } else { Double firstEnlargement = firstNode.ComputeEnlargement(node.Envelope); Double secondEnlargement = secondNode.ComputeEnlargement(node.Envelope); if (firstEnlargement < secondEnlargement) { firstNode.AddChild(node); } else if (firstEnlargement > secondEnlargement) { secondNode.AddChild(node); } else { if (firstNode.Envelope.Surface < secondNode.Envelope.Surface) { firstNode.AddChild(node); } else { secondNode.AddChild(node); } } } } }
/// <summary> /// Clears all geometries from the index. /// </summary> public void Clear() { _root = new RTreeNode(_root.MaxChildren); _height = 0; _numberOfGeometries = 0; }
/// <summary> /// Initializes a new instance of the <see cref="RTreeNode" /> class. /// </summary> /// <param name="parent">The parent of the node.</param> /// <param name="geometry">The <see cref="IGeometry" /> contained by the node.</param> public RTreeNode(IGeometry geometry, RTreeNode parent = null) : this(parent) { Geometry = geometry; }
/// <summary> /// Initializes a new instance of the <see cref="RTreeNode" /> class. /// </summary> /// <param name="parent">The parent of the node.</param> public RTreeNode(RTreeNode parent) { Parent = parent; }
public override Envelope GetExtents() { if (_cachedExtents != null) { return(new Envelope(_cachedExtents)); } Envelope box = null; if (_spatiaLiteIndex == SpatiaLiteIndex.RTree) { using (var conn = new SQLiteConnection(ConnectionString)) { conn.Open(); var strSQL = string.Format("SELECT \"data\" FROM \"idx_{0}_{1}_node\" WHERE \"nodeno\"=1;", _table, _geometryColumn); using (var cmd = conn.CreateCommand()) { cmd.CommandText = strSQL; var result = cmd.ExecuteScalar(); if (result != null && result != DBNull.Value) { var buffer = (byte[])result; var node = new RTreeNode(buffer); _cachedExtents = float.IsNaN(node.XMin) ? new Envelope() : new Envelope(node.XMin, node.XMax, node.YMin, node.YMax); return(new Envelope(_cachedExtents)); //var entities = new float[2*_numOrdinateDimensions]; //var offset = 12; //for (var i = 0; i < 2*_numOrdinateDimensions; i++) //{ // Array.Reverse(buffer, offset, 4); // entities[i] = BitConverter.ToSingle(buffer, offset); // offset += 4; //} //return new Envelope(entities[0], entities[2], entities[1], entities[3]); } throw new Exception(); } } } using (SQLiteConnection conn = SpatiaLiteConnection(ConnectionString)) { //string strSQL = "SELECT Min(minx) AS MinX, Min(miny) AS MinY, Max(maxx) AS MaxX, Max(maxy) AS MaxY FROM " + this.Table; string strSQL; if (_spatiaLiteIndex == SpatiaLiteIndex.RTree && String.IsNullOrEmpty(_definitionQuery)) { strSQL = string.Format( "SELECT MIN(xmin) AS minx, MAX(xmax) AS maxx, MIN(ymin) AS miny, MAX(ymax) AS maxy from {0};", string.Format("idx_{0}_{1}", _table, _geometryColumn)); } else { strSQL = string.Format( "SELECT MIN(MbrMinX({0})) AS minx, MIN(MbrMinY({0})) AS miny, MAX(MbrMaxX({0})) AS maxx, MAX(MbrMaxY({0})) AS maxy FROM {1};", _geometryColumn, FromClause(_table)); } using (var command = new SQLiteCommand(strSQL, conn)) { using (var dr = command.ExecuteReader()) if (dr.Read()) { if (dr.IsDBNull(0)) { return(new Envelope(0, 0, 0, 0)); } box = new Envelope( (double)dr["minx"], (double)dr["maxx"], (double)dr["miny"], (double)dr["maxy"]); } conn.Close(); } _cachedExtents = box; return(new Envelope(box)); } }