/*! Constructs a DefaultCatalog with given signature and language and reads the catalog from disk. InitCheck() will be B_OK if catalog could be loaded successfully, it will give an appropriate error-code otherwise. */ DefaultCatalog::DefaultCatalog(const entry_ref &catalogOwner, const char *language, uint32 fingerprint) : HashMapCatalog("", language, fingerprint) { // We created the catalog with an invalid signature, but we fix that now. SetSignature(catalogOwner); status_t status; // search for catalog living in sub-folder of app's folder: node_ref nref; nref.device = catalogOwner.device; nref.node = catalogOwner.directory; BDirectory appDir(&nref); BString catalogName("locale/"); catalogName << kCatFolder << "/" << fSignature << "/" << fLanguageName << kCatExtension; BPath catalogPath(&appDir, catalogName.String()); status = ReadFromFile(catalogPath.Path()); if (status != B_OK) { // search in data folders directory_which which[] = { B_USER_DATA_DIRECTORY, B_COMMON_DATA_DIRECTORY, B_SYSTEM_DATA_DIRECTORY }; for (size_t i = 0; i < sizeof(which) / sizeof(which[0]); i++) { BPath path; if (find_directory(which[i], &path) == B_OK) { BString catalogName(path.Path()); catalogName << "/locale/" << kCatFolder << "/" << fSignature << "/" << fLanguageName << kCatExtension; status = ReadFromFile(catalogName.String()); if (status == B_OK) break; } } } if (status != B_OK) { // give lowest priority to catalog embedded as resource in application // executable, so they can be overridden easily. status = ReadFromResource(catalogOwner); } fInitCheck = status; }
__declspec(dllexport) int CalculatePairwiseGeodesicDistances(const wchar_t* feature_class, const wchar_t* output_file, const double unit_factor, const bool is_spagedi) { std::ofstream fs(output_file); if (!fs) { std::cerr << "Cannot open the output file." <<std::endl; return -1; } // Convert wchar_t*s to bstring _bstr_t catalogPath(feature_class); // Coinitialize GP utilities class IGPUtilitiesPtr ipUtil(CLSID_GPUtilities); // Feature class holder IFeatureClassPtr ipFeatureclass(0); HRESULT hr; // Try to fetch feature class from catalog path if (FAILED(hr = ipUtil->OpenFeatureClassFromString(catalogPath, &ipFeatureclass))) { fs << "Failed to open: " << catalogPath << std::endl; return -2; } // Set up query and filter IQueryFilterPtr ipFilter(CLSID_QueryFilter); IFeatureCursorPtr ipCursor; IFeaturePtr ipRow; IGeometryPtr ipGeometry; esriGeometryType gt; // coordinate system IGeographicCoordinateSystemPtr pGCS; ISpatialReferenceFactoryPtr pSpatRefFactory(CLSID_SpatialReferenceEnvironment); ISpatialReferencePtr spatialReference; // use meters as default linear units IUnitPtr ipUnit; pSpatRefFactory->CreateUnit(esriSRUnit_Meter, &ipUnit); ILinearUnitPtr linearUnit = ipUnit; // get the feature count to initialize our output matrix long featureCount; ipFeatureclass->FeatureCount(NULL, &featureCount); // initialize the 2d matrix (array of pointers) double** matrix = new double*[featureCount]; IPointArrayPtr ipPointArray; ipPointArray.CreateInstance(CLSID_PointArray); long* oids = new long[featureCount]; // Currently, this is only set to run as a 32-bit process, and // it'll crash if the application tries to use more than ~1.5GB // of memory. Approximate the dimensions that we'd expect to work // and fail if the user exceeds these limits. double arrayMemUsage = (8.0 * pow((double)featureCount, 2)) / pow(1024.0,2); if (arrayMemUsage > 1200) return -3; // Open search cursor on feature class ipFeatureclass->Search(ipFilter, VARIANT_FALSE, &ipCursor); int i = 0; for (ipCursor->NextFeature(&ipRow); ipRow != NULL; ipCursor->NextFeature(&ipRow)) { long oid_val; ipRow->get_OID(&oid_val); oids[i] = oid_val; ipRow->get_Shape(&ipGeometry); IPointPtr ipPoint (ipGeometry); if (i == 0) { // make sure inputs are points ipGeometry->get_GeometryType(>); if (gt != esriGeometryPoint) return -4; } // push the point onto our array ipPointArray->Add(ipPoint); // initialize output matrix element for this point matrix[i] = new double[featureCount]; i++; } // still have a poiner to the last referenced geometry, use // this to set the computation spatial reference. ipGeometry->get_SpatialReference(&spatialReference); // geometry server IGeometryServer2Ptr geomServer; geomServer.CreateInstance(CLSID_GeometryServerImpl); IRelationalOperatorPtr ipRelOp; double distance; for (int i = 0; i < featureCount; i++) { //fs << "at distance calculation for row " << i << std::endl; IPointPtr ipPointFrom; IPointPtr ipPointTo; // "(typeid: " << typeid(coord_vals[i][2]).name() << std::endl; ipPointFrom.CreateInstance(CLSID_Point); ipPointTo.CreateInstance(CLSID_Point); ipPointArray->get_Element(i, &ipPointFrom); // set up a relational operator for this point ipRelOp = ipPointFrom; for (int j = 0; j < featureCount; j++) { if (i == j) { distance = 0; } else if (matrix[j][i] > 0) { //fs << "matrix[j][i] is not NULL, value is `" << matrix[j][i] << // "`, type " << typeid(matrix[j][i]).name() << std::endl; distance = matrix[j][i]; } else { ipPointArray->get_Element(j, &ipPointTo); VARIANT_BOOL bEquals; ipRelOp->Equals(ipPointTo, &bEquals); if (bEquals) { distance = 0; } else { //fs << "try to get geodesic distance..." << std::endl; //double from_x, from_y, to_x, to_y; //ipPointFrom->QueryCoords(&from_x, &from_y); //ipPointTo->QueryCoords(&to_x, &to_y); //fs << "dist from: (" << from_x << "," << from_y << ")" << // " to (" << to_x << "," << to_y << ") with sr `" << // spatialReference << "`, unit factor " << unit_factor << "." << std::endl; geomServer->GetDistanceGeodesic(spatialReference, ipPointFrom, ipPointTo, linearUnit, &distance); // rescale distance by the unit factor (current unit releative to meters) distance = distance * unit_factor; } } matrix[i][j] = distance; } } // two possible output formats: 'standard' and 'SPAGeDi'. const char sep = is_spagedi ? '\t' : ','; if (is_spagedi) { fs << "M" << featureCount << sep; } // write header row for (int h = 0; h < featureCount; h++) { fs << sep << oids[h]; } fs << std::endl; // write out results for (int i = 0; i < featureCount; i++) { fs << oids[i] << sep; for (int j = 0; j < featureCount - 1; j++) { fs << std::fixed << matrix[i][j] << sep; } fs << std::fixed << matrix[i][featureCount - 1] << std::endl; } if (is_spagedi) { fs << "END" << std::endl; } fs.close(); return 0; }