// utility function - given a layerset, add all its placenamesets to the above collection, recursing into child layers private void collectTiledPlacenamesSets(LayerSet.Type_LayerSet curLayerSet) { if (curLayerSet.HasTiledPlacenameSet()) // any placenames at all? { // yes, iterate over them for (int i = 0; i < curLayerSet.TiledPlacenameSetCount; i++) { // get tilesplacenameset LayerSet.Type_TiledPlacenameSet2 tpns = curLayerSet.GetTiledPlacenameSetAt(i); // compute full path to wpl file - WplIndex constructor needs this string wplFullPath = Path.Combine(MainApplication.DirectoryPath, tpns.PlacenameListFilePath.Value); // build an index descriptor (does not create or load the index yet) WplIndex idx = new WplIndex(tpns, wplFullPath); // an indexedTilePlacenameSet associates the index descriptor with the placenameset IndexedTiledPlaceNameSet ipns = new IndexedTiledPlaceNameSet(tpns, idx); // add them to our collection this.indexedTiledPlacenameSets.Add(ipns); } } // now recurse into child layers of this set and do the same if (curLayerSet.HasChildLayerSet()) { for (int i = 0; i < curLayerSet.ChildLayerSetCount; i++) { this.collectTiledPlacenamesSets(curLayerSet.GetChildLayerSetAt(i)); } } }
// this is the "fast find" or quick variant of the search. Does not search attributes and needs exact // names, but much faster due to indexed binary search bool PlaceNameSetQuickSearch(string searchString, IndexedTiledPlaceNameSet itps, bool bPartial) { try { // return false if stop requested if (CheckStopRequested()) { return(false); } itps.wplIndex.Lock(null); // load and lock index // find using binary search int nRet = itps.wplIndex.FindPlaceByName(searchString, bPartial); if (nRet < 0) { return(true); // didn't find anything, return indicating "go on" } // found one - add it and its matching neighbours. bool ret; ret = AddIndexAndVicinity(nRet, itps, searchString, bPartial); return(ret); } finally { // don't forget to release the index itps.wplIndex.Release(); } }
// perform a full search in a placename set, with attributes bool PlaceNameSetFullSearch(string [] searchTokens, IndexedTiledPlaceNameSet curIndexedTiledSet) { DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName( Path.Combine( Path.GetDirectoryName(Application.ExecutablePath), curIndexedTiledSet.placenameSet.PlacenameListFilePath.Value))); // ignore this set if the corresponding directory does not exist for some reason if (!dir.Exists) { return(true); } // loop over all WWP files in directory foreach (FileInfo placenameFile in dir.GetFiles("*.wwp")) { using (BinaryReader reader = new BinaryReader(placenameFile.OpenRead())) { int placenameCount = reader.ReadInt32(); // loop over all places for (int i = 0; i < placenameCount; i++) { // return false if stop requested if (CheckStopRequested()) { return(false); } // instantiate and read current placename WorldWindPlacename pn = new WorldWindPlacename(); WplIndex.ReadPlaceName(reader, ref pn, WplIndex.MetaDataAction.Store); // if we have a match ... if (isPlaceMatched(searchTokens, pn)) { if (CheckMaxResults()) { return(false); } PlaceItem pi = new PlaceItem(); pi.pn = pn; pi.placeDescriptor = curIndexedTiledSet.placenameSet; // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); } } } } return(true); // go on }
// adds a place (given by index) found via binary search to the list, and adds places above and below it // in the sort order as long as they match bool AddIndexAndVicinity(int nPos, IndexedTiledPlaceNameSet itps, string strSearch, bool bPartialAllowed) { PlaceItem pi = itps.wplIndex.GetPlaceItem(nPos); // get the place from the index // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); // instantiate our special comparer - will compare search string to a place given by index - this is the same one // we're using in the binary search WplIndex.IndexEntryToStringComparer cmp = new WplIndex.IndexEntryToStringComparer(itps.wplIndex, bPartialAllowed); int nBelow = nPos - 1; // left neighbour in search order (if any) int nAbove = nPos + 1; // right neighbour in search order (if any) bool bFoundOne; // keeps track if "expansion mechanism" still found something do { // return false if stop requested or too many results if (CheckStopRequested() || CheckMaxResults()) { return(false); } bFoundOne = false; if (itps.wplIndex.IsValidIndex(nBelow) && cmp.Compare(nBelow, strSearch) == 0) { // left neighbour index valid and matched pi = itps.wplIndex.GetPlaceItem(nBelow); // get the data // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); --nBelow; // expand to the left bFoundOne = true; } if (itps.wplIndex.IsValidIndex(nAbove) && cmp.Compare(nAbove, strSearch) == 0) { // right neighbour index valid and matched pi = itps.wplIndex.GetPlaceItem(nAbove); // get the data // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); ++nAbove; // expand to the left bFoundOne = true; } } while(bFoundOne); // keep expanding until nothing new on both sides return(true); // keep searching }
private void checkBoxFastSearch_CheckedChanged(object sender, System.EventArgs e) { // if transition from checked to unchecked or all indices are available, that's OK if (!checkBoxFastSearch.Checked || this.AllIndicesAvailable()) { return; } if (MessageBox.Show("Fast search requires precomputed index files that were not found.\n\n" + "PlaceFinder can compute these now, but this requires large amounts of \n" + "memory and World Wind may temporarily appear 'frozen'.\n\n" + "Before you proceed, save your work and close other applications\n" + "to free more memory. Once the index files are created, you won't see\n" + "this message again.", "Compute missing indices?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { this.progressBarSearch.Minimum = 0; this.progressBarSearch.Maximum = 100; string savedTitle = this.Text; for (int i = 0; i < indexedTiledPlacenameSets.Count; i++) { this.Text = String.Format(savedTitle + " : Computing index {0} of {1}", i, indexedTiledPlacenameSets.Count); IndexedTiledPlaceNameSet tpns = (IndexedTiledPlaceNameSet)indexedTiledPlacenameSets[i]; if (!tpns.wplIndex.IsAvailable) { tpns.wplIndex.CreateIndex(new WplIndex.ProgressReportDelegate(IndexCreationProgressDelegate)); GC.Collect(); } } SetStopped("Done."); this.Text = savedTitle; } else { checkBoxFastSearch.Checked = false; } }
// this is the "fast find" or quick variant of the search. Does not search attributes and needs exact // names, but much faster due to indexed binary search bool PlaceNameSetQuickSearch(string searchString, IndexedTiledPlaceNameSet itps, bool bPartial) { try { // return false if stop requested if(CheckStopRequested()) { return false; } itps.wplIndex.Lock(null); // load and lock index // find using binary search int nRet = itps.wplIndex.FindPlaceByName(searchString, bPartial); if(nRet < 0) { return true; // didn't find anything, return indicating "go on" } // found one - add it and its matching neighbours. bool ret; ret = AddIndexAndVicinity(nRet, itps, searchString, bPartial); return ret; } finally { // don't forget to release the index itps.wplIndex.Release(); } }
// adds a place (given by index) found via binary search to the list, and adds places above and below it // in the sort order as long as they match bool AddIndexAndVicinity(int nPos, IndexedTiledPlaceNameSet itps, string strSearch, bool bPartialAllowed) { PlaceItem pi = itps.wplIndex.GetPlaceItem(nPos); // get the place from the index // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); // instantiate our special comparer - will compare search string to a place given by index - this is the same one // we're using in the binary search WplIndex.IndexEntryToStringComparer cmp = new WplIndex.IndexEntryToStringComparer(itps.wplIndex, bPartialAllowed); int nBelow = nPos-1; // left neighbour in search order (if any) int nAbove = nPos+1; // right neighbour in search order (if any) bool bFoundOne; // keeps track if "expansion mechanism" still found something do { // return false if stop requested or too many results if(CheckStopRequested() || CheckMaxResults()) { return false; } bFoundOne = false; if(itps.wplIndex.IsValidIndex(nBelow) && cmp.Compare(nBelow, strSearch) == 0) { // left neighbour index valid and matched pi = itps.wplIndex.GetPlaceItem(nBelow); // get the data // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); --nBelow; // expand to the left bFoundOne = true; } if(itps.wplIndex.IsValidIndex(nAbove) && cmp.Compare(nAbove, strSearch) == 0) { // right neighbour index valid and matched pi = itps.wplIndex.GetPlaceItem(nAbove); // get the data // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); ++nAbove; // expand to the left bFoundOne = true; } } while(bFoundOne); // keep expanding until nothing new on both sides return true; // keep searching }
// perform a full search in a placename set, with attributes bool PlaceNameSetFullSearch(string [] searchTokens, IndexedTiledPlaceNameSet curIndexedTiledSet) { DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName( Path.Combine( Path.GetDirectoryName(Application.ExecutablePath), curIndexedTiledSet.placenameSet.PlacenameListFilePath.Value))); // ignore this set if the corresponding directory does not exist for some reason if(!dir.Exists) return true; // loop over all WWP files in directory foreach(FileInfo placenameFile in dir.GetFiles("*.wwp")) { using(BinaryReader reader = new BinaryReader(placenameFile.OpenRead()) ) { int placenameCount = reader.ReadInt32(); // loop over all places for(int i = 0; i < placenameCount; i++) { // return false if stop requested if(CheckStopRequested()) return false; // instantiate and read current placename WorldWindPlacename pn = new WorldWindPlacename(); WplIndex.ReadPlaceName(reader, ref pn, WplIndex.MetaDataAction.Store); // if we have a match ... if(isPlaceMatched(searchTokens, pn)) { if(CheckMaxResults()) return false; PlaceItem pi = new PlaceItem(); pi.pn = pn; pi.placeDescriptor = curIndexedTiledSet.placenameSet; // add item via delegate to avoid MT issues listViewResults.Invoke(listViewResults.addPlaceDelegate, new object[] { pi }); } } } } return true; // go on }
// utility function - given a layerset, add all its placenamesets to the above collection, recursing into child layers private void collectTiledPlacenamesSets(LayerSet.Type_LayerSet curLayerSet) { if(curLayerSet.HasTiledPlacenameSet()) // any placenames at all? { // yes, iterate over them for(int i = 0; i < curLayerSet.TiledPlacenameSetCount; i++) { // get tilesplacenameset LayerSet.Type_TiledPlacenameSet2 tpns = curLayerSet.GetTiledPlacenameSetAt(i); // compute full path to wpl file - WplIndex constructor needs this string wplFullPath = Path.Combine(MainApplication.DirectoryPath, tpns.PlacenameListFilePath.Value); // build an index descriptor (does not create or load the index yet) WplIndex idx = new WplIndex(tpns, wplFullPath); // an indexedTilePlacenameSet associates the index descriptor with the placenameset IndexedTiledPlaceNameSet ipns = new IndexedTiledPlaceNameSet(tpns, idx); // add them to our collection this.indexedTiledPlacenameSets.Add(ipns); } } // now recurse into child layers of this set and do the same if(curLayerSet.HasChildLayerSet()) { for(int i = 0; i < curLayerSet.ChildLayerSetCount; i++) { this.collectTiledPlacenamesSets(curLayerSet.GetChildLayerSetAt(i)); } } }