//---------------------------------------------------------------------------// // Search the domain with the range entity centroids and construct the // graph. This will update the state of the object. void ParallelSearch::search( const EntityIterator& range_iterator, const Teuchos::RCP<EntityLocalMap>& range_local_map, const Teuchos::ParameterList& parameters ) { // Set the parameters with the local map. range_local_map->setParameters( parameters ); // Empty range flag. d_empty_range = ( 0 == range_iterator.size() ); // Reset the state of the object. d_range_owner_ranks.clear(); d_domain_to_range_map.clear(); d_range_to_domain_map.clear(); d_parametric_coords.clear(); // Perform a coarse global search to redistribute the range entities. Teuchos::Array<EntityId> range_entity_ids; Teuchos::Array<int> range_owner_ranks; Teuchos::Array<double> range_centroids; d_coarse_global_search->search( range_iterator, range_local_map, parameters, range_entity_ids, range_owner_ranks, range_centroids ); // If needed, extract the range entities that were missed during the // coarse global search. Teuchos::Array<EntityId> found_range_entity_ids; Teuchos::Array<int> found_range_ranks; Teuchos::Array<EntityId> missed_range_entity_ids; Teuchos::Array<int> missed_range_ranks; if ( d_track_missed_range_entities ) { missed_range_entity_ids = Teuchos::Array<EntityId>( d_coarse_global_search->getMissedRangeEntityIds() ); missed_range_ranks.assign( missed_range_entity_ids.size(), d_comm->getRank() ); } // Only do the local search if there are local domain entities. Teuchos::Array<int> export_range_ranks; Teuchos::Array<EntityId> export_data; if ( !d_empty_domain ) { // For each range centroid, perform a local search. int num_range = range_entity_ids.size(); Teuchos::Array<Entity> domain_neighbors; Teuchos::Array<Entity> domain_parents; Teuchos::Array<double> reference_coordinates; Teuchos::Array<double> local_coords( d_physical_dim ); int num_parents = 0; for ( int n = 0; n < num_range; ++n ) { // Perform a coarse local search to get the nearest domain // entities to the point. d_coarse_local_search->search( range_centroids(d_physical_dim*n,d_physical_dim), parameters, domain_neighbors ); // Perform a fine local search to get the entities the point maps // to. d_fine_local_search->search( domain_neighbors, range_centroids(d_physical_dim*n,d_physical_dim), parameters, domain_parents, reference_coordinates ); // Store the potentially multiple parametric realizations of the // point. std::unordered_map<EntityId,Teuchos::Array<double> > ref_map; num_parents = domain_parents.size(); for ( int p = 0; p < num_parents; ++p ) { // Store the range data in the domain parallel decomposition. local_coords().assign( reference_coordinates(d_physical_dim*p,d_physical_dim) ); d_range_owner_ranks.emplace( range_entity_ids[n], range_owner_ranks[n] ); d_domain_to_range_map.emplace( domain_parents[p].id(), range_entity_ids[n] ); ref_map.emplace( domain_parents[p].id(), local_coords ); // Extract the data to communicate back to the range parallel // decomposition. export_range_ranks.push_back( range_owner_ranks[n] ); export_data.push_back( range_entity_ids[n] ); export_data.push_back( domain_parents[p].id() ); export_data.push_back( Teuchos::as<EntityId>(d_comm->getRank()) ); } // If we found parents for the point, store them. if ( num_parents > 0 ) { d_parametric_coords.emplace( range_entity_ids[n], ref_map ); // If we are tracking missed entities, also track those that // we found so we can determine if an entity was found after // being sent to multiple destinations. if ( d_track_missed_range_entities ) { found_range_entity_ids.push_back( range_entity_ids[n] ); found_range_ranks.push_back( range_owner_ranks[n] ); } } // Otherwise, if we are tracking missed entities report this. else if ( d_track_missed_range_entities ) { missed_range_entity_ids.push_back( range_entity_ids[n] ); missed_range_ranks.push_back( range_owner_ranks[n] ); } } } // Back-communicate the domain entities in which we found each range // entity to complete the mapping. Tpetra::Distributor domain_to_range_dist( d_comm ); int num_import = domain_to_range_dist.createFromSends( export_range_ranks() ); Teuchos::Array<EntityId> domain_data( 3*num_import ); Teuchos::ArrayView<const EntityId> export_data_view = export_data(); domain_to_range_dist.doPostsAndWaits( export_data_view, 3, domain_data() ); // Store the domain data in the range parallel decomposition. for ( int i = 0; i < num_import; ++i ) { d_domain_owner_ranks.emplace( domain_data[3*i+1], domain_data[3*i+2] ); d_range_to_domain_map.emplace( domain_data[3*i], domain_data[3*i+1] ); } // If we are tracking missed entities, back-communicate the missing entities // and found entities to determine which entities are actually missing. if ( d_track_missed_range_entities ) { // Back-communicate the missing entities. Tpetra::Distributor missed_range_dist( d_comm ); int num_import_missed = missed_range_dist.createFromSends( missed_range_ranks() ); Teuchos::Array<EntityId> import_missed( num_import_missed ); Teuchos::ArrayView<const EntityId> missed_view = missed_range_entity_ids(); missed_range_dist.doPostsAndWaits( missed_view, 1, import_missed() ); // Back-communicate the found entities. Tpetra::Distributor found_range_dist( d_comm ); int num_import_found = found_range_dist.createFromSends( found_range_ranks() ); Teuchos::Array<EntityId> import_found( num_import_found ); Teuchos::ArrayView<const EntityId> found_view = found_range_entity_ids(); found_range_dist.doPostsAndWaits( found_view, 1, import_found() ); // Intersect the found and missed entities to determine if there are any // that were found on one process but missed on another. std::sort( import_missed.begin(), import_missed.end() ); std::sort( import_found.begin(), import_found.end() ); Teuchos::Array<EntityId> false_positive_missed( import_missed.size() + import_found.size() ); auto false_positive_end = std::set_intersection( import_missed.begin(), import_missed.end(), import_found.begin(), import_found.end(), false_positive_missed.begin() ); // Create a list of missed entities without the false positives. d_missed_range_entity_ids.resize( num_import_missed ); auto missed_range_end = std::set_difference( import_missed.begin(), import_missed.end(), false_positive_missed.begin(), false_positive_end, d_missed_range_entity_ids.begin() ); // Create a unique list of missed entities without the false positives. std::sort( d_missed_range_entity_ids.begin(), missed_range_end ); auto missed_range_unique_end = std::unique( d_missed_range_entity_ids.begin(), missed_range_end ); d_missed_range_entity_ids.resize( std::distance(d_missed_range_entity_ids.begin(), missed_range_unique_end) ); } }
// This is called when user presses enter in the location input // or selects a location from the typed locations dropdown. void LLNavigationBar::onLocationSelection() { std::string typed_location = mCmbLocation->getSimple(); LLStringUtil::trim(typed_location); // Will not teleport to empty location. if (typed_location.empty()) return; //get selected item from combobox item LLSD value = mCmbLocation->getSelectedValue(); if(value.isUndefined() && !mCmbLocation->getTextEntry()->isDirty()) { // At this point we know that: there is no selected item in list and text field has NOT been changed // So there is no sense to try to change the location return; } /* since navbar list support autocompletion it contains several types of item: landmark, teleport hystory item, * typed by user slurl or region name. Let's find out which type of item the user has selected * to make decision about adding this location into typed history. see mSaveToLocationHistory * Note: * Only TYPED_REGION_SLURL item will be added into LLLocationHistory */ if(value.has("item_type")) { switch(value["item_type"].asInteger()) { case LANDMARK: if(value.has("AssetUUID")) { gAgent.teleportViaLandmark( LLUUID(value["AssetUUID"].asString())); return; } else { LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(typed_location, FALSE); if (!landmark_items.empty()) { gAgent.teleportViaLandmark( landmark_items[0]->getAssetUUID()); return; } } break; case TELEPORT_HISTORY: //in case of teleport item was selected, teleport by position too. case TYPED_REGION_SLURL: if(value.has("global_pos")) { gAgent.teleportViaLocation(LLVector3d(value["global_pos"])); return; } break; default: break; } } //Let's parse slurl or region name std::string region_name; LLVector3 local_coords(128, 128, 0); S32 x = 0, y = 0, z = 0; // Is the typed location a SLURL? if (LLSLURL::isSLURL(typed_location)) { // Yes. Extract region name and local coordinates from it. if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), ®ion_name, &x, &y, &z)) local_coords.set(x, y, z); else return; } // we have to do this check after previous, because LLUrlRegistry contains handlers for slurl too //but we need to know whether typed_location is a simple http url. else if (LLUrlRegistry::instance().isUrl(typed_location)) { // display http:// URLs in the media browser, or // anything else is sent to the search floater LLWeb::loadURL(typed_location); return; } else { // assume that an user has typed the {region name} or possible {region_name, parcel} region_name = typed_location.substr(0,typed_location.find(',')); } // Resolve the region name to its global coordinates. // If resolution succeeds we'll teleport. LLWorldMapMessage::url_callback_t cb = boost::bind( &LLNavigationBar::onRegionNameResponse, this, typed_location, region_name, local_coords, _1, _2, _3, _4); mSaveToLocationHistory = true; LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false); }