public void CanRegisterTestedFeature() { var overlaps = new OverlappingFeatures(); var fc = new FeatureClassMock(1, "", esriGeometryType.esriGeometryPolyline); IFeature feature = fc.CreateFeature(new Pt(0, 0), new Pt(9.95, 9.95)); var cachedRow = new CachedRow(feature); overlaps.RegisterTestedFeature(cachedRow, null); }
/// <summary> /// Centroids near Tile borders may exist twice /// </summary> private static int GetReducedCount([NotNull] ICollection <IRow> centroids) { if (centroids.Count < 2) { return(centroids.Count); } var reducedList = new Dictionary <BaseRow, IRow>(new BaseRowComparer()); foreach (IRow row in centroids) { var centroid = (IFeature)row; var add = new CachedRow(centroid); if (reducedList.ContainsKey(add) == false) { reducedList.Add(add, centroid); } } return(reducedList.Count); }
/// <summary> /// Requests a block of parts. /// </summary> /// <param name="resultId"></param> /// <param name="rowIndex"></param> /// <param name="rowCount"></param> /// <param name="colCount"></param> /// <param name="totalRowCount"></param> /// <remarks> /// If the block can be completely retrieved from the cache then it is /// done so. Otherwise, it forwards the request for the rows onto the /// connection object. /// </remarks> /// <returns></returns> public QueryResultPart GetResultPart(int resultId, int rowIndex, int rowCount, int colCount, int totalRowCount) { lock (this) { // What was requested.... int origRowIndex = rowIndex; int origRowCount = rowCount; var cachedRows = new List<CachedRow>(); // The top row that isn't found in the cache. bool foundNotcached = false; // Look for the top row in the block that hasn't been cached for (int r = 0; r < rowCount && !foundNotcached; ++r) { int daRow = rowIndex + r; // Is the row in the cache? var rowRef = new RowRef(resultId, daRow); // Not in cache so mark this as top row not in cache... object rowObj; if (!rowCache.TryGet(rowRef, out rowObj)) { rowIndex = daRow; if (rowIndex + rowCount > totalRowCount) { rowCount = totalRowCount - rowIndex; } foundNotcached = true; } else { var row = (CachedRow) rowObj; cachedRows.Add(row); } } var notCachedRows = new List<CachedRow>(); if (foundNotcached) { // Now work up from the bottom and find row that isn't in cache.... foundNotcached = false; // Look for the bottom row in the block that hasn't been cached for (int r = rowCount - 1; r >= 0 && !foundNotcached; --r) { int daRow = rowIndex + r; // Is the row in the cache? var rowRef = new RowRef(resultId, daRow); // Not in cache so mark this as top row not in cache... object rowObj; if (!rowCache.TryGet(rowRef, out rowObj)) { if (rowIndex == origRowIndex) { rowIndex = rowIndex - (rowCount - (r + 1)); if (rowIndex < 0) { rowCount = rowCount + rowIndex; rowIndex = 0; } } else { rowCount = r + 1; } foundNotcached = true; } else { var row = (CachedRow) rowObj; notCachedRows.Insert(0, row); } } } // Some of it not in the cache... if (foundNotcached) { // Request a part of a result from the server (blocks) QueryResultPart block = connection.RequestResultPart(resultId, rowIndex, rowCount); for (int r = 0; r < rowCount; ++r) { var rowData = new ISqlObject[block.ColumnCount]; var dataSizes = new int[block.ColumnCount]; int theRow = (rowIndex + r); int colSize = 0; var row = block.GetRow(r); for (int c = 0; c < colCount; ++c) { var ob = row.Values[c]; rowData[c] = ob; dataSizes[c] = row.ValueSizes[c]; colSize += row.ValueSizes[c]; } var cachedRow = new CachedRow { ResultId = resultId, Row = theRow, RowData = rowData, Sizes = dataSizes }; // Don't cache if it's over a certain size, if (colSize <= 3200) { rowCache.Set(new RowRef(resultId, theRow), cachedRow); } cachedRows.Add(cachedRow); } } // At this point, the cached rows should be completely in the cache so // retrieve it from the cache. var resultPart = new QueryResultPart(colCount); int low = origRowIndex; int high = origRowIndex + origRowCount; foreach (CachedRow row in cachedRows) { if (row.ResultId != resultId) continue; // Put into the result block if (row.Row >= low && row.Row < high) { var rowArray = new ISqlObject[colCount]; var rowSizes = new int[colCount]; for (int c = 0; c < colCount; ++c) { rowArray[c] = row.RowData[c]; rowSizes[c] = row.Sizes[c]; } resultPart.AddRow(new QueryResultRow(rowArray, rowSizes)); } } foreach (CachedRow row in notCachedRows) { if (row.ResultId != resultId) continue; // Put into the result block if (row.Row >= low && row.Row < high) { var rowArray = new ISqlObject[colCount]; var sizes = new int[colCount]; for (int c = 0; c < colCount; ++c) { rowArray[c] = row.RowData[c]; sizes[c] = row.Sizes[c]; } resultPart.AddRow(new QueryResultRow(rowArray, sizes)); } } // And return the result (phew!) return resultPart; } }
/// <summary> /// Requests a block of parts. /// </summary> /// <param name="resultId"></param> /// <param name="rowIndex"></param> /// <param name="rowCount"></param> /// <param name="colCount"></param> /// <param name="totalRowCount"></param> /// <remarks> /// If the block can be completely retrieved from the cache then it is /// done so. Otherwise, it forwards the request for the rows onto the /// connection object. /// </remarks> /// <returns></returns> public QueryResultPart GetResultPart(int resultId, int rowIndex, int rowCount, int colCount, int totalRowCount) { lock (this) { // What was requested.... int origRowIndex = rowIndex; int origRowCount = rowCount; var cachedRows = new List <CachedRow>(); // The top row that isn't found in the cache. bool foundNotcached = false; // Look for the top row in the block that hasn't been cached for (int r = 0; r < rowCount && !foundNotcached; ++r) { int daRow = rowIndex + r; // Is the row in the cache? var rowRef = new RowRef(resultId, daRow); // Not in cache so mark this as top row not in cache... object rowObj; if (!rowCache.TryGet(rowRef, out rowObj)) { rowIndex = daRow; if (rowIndex + rowCount > totalRowCount) { rowCount = totalRowCount - rowIndex; } foundNotcached = true; } else { var row = (CachedRow)rowObj; cachedRows.Add(row); } } var notCachedRows = new List <CachedRow>(); if (foundNotcached) { // Now work up from the bottom and find row that isn't in cache.... foundNotcached = false; // Look for the bottom row in the block that hasn't been cached for (int r = rowCount - 1; r >= 0 && !foundNotcached; --r) { int daRow = rowIndex + r; // Is the row in the cache? var rowRef = new RowRef(resultId, daRow); // Not in cache so mark this as top row not in cache... object rowObj; if (!rowCache.TryGet(rowRef, out rowObj)) { if (rowIndex == origRowIndex) { rowIndex = rowIndex - (rowCount - (r + 1)); if (rowIndex < 0) { rowCount = rowCount + rowIndex; rowIndex = 0; } } else { rowCount = r + 1; } foundNotcached = true; } else { var row = (CachedRow)rowObj; notCachedRows.Insert(0, row); } } } // Some of it not in the cache... if (foundNotcached) { // Request a part of a result from the server (blocks) QueryResultPart block = connection.RequestResultPart(resultId, rowIndex, rowCount); for (int r = 0; r < rowCount; ++r) { var rowData = new ISqlObject[block.ColumnCount]; var dataSizes = new int[block.ColumnCount]; int theRow = (rowIndex + r); int colSize = 0; var row = block.GetRow(r); for (int c = 0; c < colCount; ++c) { var ob = row.Values[c]; rowData[c] = ob; dataSizes[c] = row.ValueSizes[c]; colSize += row.ValueSizes[c]; } var cachedRow = new CachedRow { ResultId = resultId, Row = theRow, RowData = rowData, Sizes = dataSizes }; // Don't cache if it's over a certain size, if (colSize <= 3200) { rowCache.Set(new RowRef(resultId, theRow), cachedRow); } cachedRows.Add(cachedRow); } } // At this point, the cached rows should be completely in the cache so // retrieve it from the cache. var resultPart = new QueryResultPart(colCount); int low = origRowIndex; int high = origRowIndex + origRowCount; foreach (CachedRow row in cachedRows) { if (row.ResultId != resultId) { continue; } // Put into the result block if (row.Row >= low && row.Row < high) { var rowArray = new ISqlObject[colCount]; var rowSizes = new int[colCount]; for (int c = 0; c < colCount; ++c) { rowArray[c] = row.RowData[c]; rowSizes[c] = row.Sizes[c]; } resultPart.AddRow(new QueryResultRow(rowArray, rowSizes)); } } foreach (CachedRow row in notCachedRows) { if (row.ResultId != resultId) { continue; } // Put into the result block if (row.Row >= low && row.Row < high) { var rowArray = new ISqlObject[colCount]; var sizes = new int[colCount]; for (int c = 0; c < colCount; ++c) { rowArray[c] = row.RowData[c]; sizes[c] = row.Sizes[c]; } resultPart.AddRow(new QueryResultRow(rowArray, sizes)); } } // And return the result (phew!) return(resultPart); } }
public void CheckWasAlreadyTested() { var overlaps = new OverlappingFeatures(); var fc = new FeatureClassMock(1, "", esriGeometryType.esriGeometryPolyline); IFeature f1 = fc.CreateFeature(new Pt(100, 0), new Pt(109.95, 9.95)); IFeature f2 = fc.CreateFeature(new Pt(100, 0), new Pt(109.8, 9.8)); IFeature fx = fc.CreateFeature(new Pt(100, 0), new Pt(109.95, 9.8)); IFeature fy = fc.CreateFeature(new Pt(100, 0), new Pt(109.8, 9.95)); var c1 = new CachedRow(f1); var test = new VerifyingContainerTest(fc); var t2 = new VerifyingContainerTest(fc); var t3 = new VerifyingContainerTest(fc); overlaps.RegisterTestedFeature(c1, new ContainerTest[] { test }); Assert.IsTrue(overlaps.WasAlreadyTested(f1, test)); Assert.IsFalse(overlaps.WasAlreadyTested(f2, test)); overlaps.RegisterTestedFeature(new CachedRow(f2), new ContainerTest[] { test }); Assert.IsTrue(overlaps.WasAlreadyTested(f2, test)); overlaps.RegisterTestedFeature(new CachedRow(f2), new ContainerTest[] { test, t2 }); Assert.IsTrue(overlaps.WasAlreadyTested(f2, test)); Assert.IsTrue(overlaps.WasAlreadyTested(f2, t2)); Assert.IsFalse(overlaps.WasAlreadyTested(f2, t3)); overlaps.RegisterTestedFeature(new CachedRow(fx), new ContainerTest[] { test }); overlaps.RegisterTestedFeature(new CachedRow(fy), new ContainerTest[] { test }); overlaps.SetCurrentTile(CreateBox(100, 0, 105, 5)); Assert.IsTrue(overlaps.WasAlreadyTested(f1, test)); Assert.IsTrue(overlaps.WasAlreadyTested(f2, test)); Assert.IsTrue(overlaps.WasAlreadyTested(fx, test)); Assert.IsTrue(overlaps.WasAlreadyTested(fy, test)); overlaps.AdaptSearchTolerance(fc, 0.1); overlaps.SetCurrentTile(CreateBox(110, 0, 120, 10)); Assert.IsTrue(overlaps.WasAlreadyTested(f1, test)); Assert.IsFalse(overlaps.WasAlreadyTested(f2, test)); Assert.IsTrue(overlaps.WasAlreadyTested(fx, test)); Assert.IsTrue(overlaps.WasAlreadyTested(fy, test)); overlaps.SetCurrentTile(CreateBox(100, 10, 110, 20)); Assert.IsTrue(overlaps.WasAlreadyTested(f1, test)); Assert.IsFalse(overlaps.WasAlreadyTested(f2, test)); Assert.IsFalse(overlaps.WasAlreadyTested(fx, test)); Assert.IsTrue(overlaps.WasAlreadyTested(fy, test)); overlaps.SetCurrentTile(CreateBox(110, 10, 120, 20)); Assert.IsTrue(overlaps.WasAlreadyTested(f1, test)); Assert.IsFalse(overlaps.WasAlreadyTested(f2, test)); Assert.IsFalse(overlaps.WasAlreadyTested(fx, test)); Assert.IsFalse(overlaps.WasAlreadyTested(fy, test)); overlaps.SetCurrentTile(CreateBox(110.1, 10, 120, 20)); Assert.IsFalse(overlaps.WasAlreadyTested(f1, test)); Assert.IsFalse(overlaps.WasAlreadyTested(f2, test)); Assert.IsFalse(overlaps.WasAlreadyTested(fx, test)); Assert.IsFalse(overlaps.WasAlreadyTested(fy, test)); }