void split(Side_List **sideListH, long nodeNum) { // **sideListH; Listing of the sides in the domain for splitting DAG tree // nodeNum; The index for the segment from sideList to use for pivot/split in DAG tree long numSidesL =0; // the number of sides that are split off to the left long numSidesR =0; // the number of sides that are split off to the right Side_List **sidesLeftH = nil; // pointer to area of heap where sides are left Side_List **sidesRightH = nil; // pointer to area of hear where sides are left long numSideInList = _GetHandleSize((Handle)sideListH)/(sizeof(Side_List)); // The number of sides for splitting long location,i; long nodeP1,nodeP2; Side_List sideListForNode; long bCounterL =0, bCounterR =0; // counting the number of boundary seg in a side list long branchNum; static long nsx = 0; nsx++; if(nsx == 964) { nsx = 0; } if(gErrStr[0] ) goto done; if(sideListH == nil) { strcpy(gErrStr,"Nil handle passed to split"); goto done; } branchNum = gDagTree.numBranches; IncrementGDagTree(); (*gDagTree.treeHdl)[branchNum].topoIndex = oldNodeNum(((*sideListH)[nodeNum]).p1,((*sideListH)[nodeNum]).p2); sidesLeftH = (Side_List **)_NewHandleClear((numSideInList)*sizeof(Side_List)); if(!sidesLeftH) { strcpy(gErrStr,"Out of memory in split"); goto done; } sidesRightH = (Side_List **)_NewHandleClear((numSideInList)*sizeof(Side_List)); if(!sidesRightH) { strcpy(gErrStr,"Out of memory in split"); goto done; } // find the node's points for determining relative right and left nodeP1 = (*sideListH)[nodeNum].p1; nodeP2 = (*sideListH)[nodeNum].p2; // Do the actual splitting for (i=0; i<numSideInList; i++) { if(i == nodeNum) continue; // skip the case that nodeNum = i // find the points associated with the test side location = Right_or_Left(nodeP1,nodeP2,(*sideListH)[i].p1,(*sideListH)[i].p2); // Distribute the sides to the two R/L areas of the heap switch(location) { case -1:// left (*sidesLeftH)[numSidesL++] = (*sideListH)[i];// copy the structure break; case 1: // right (*sidesRightH)[numSidesR++] = (*sideListH)[i];// copy the structure break; case 0: // both (*sidesLeftH)[numSidesL++] = (*sideListH)[i];// copy the structure (*sidesRightH)[numSidesR++] = (*sideListH)[i];// copy the structure break; } } // trim sidesL and sidesR to numSidesL and numSidesR, respectively _SetHandleSize((Handle)sidesLeftH,(numSidesL)*sizeof(Side_List)); _SetHandleSize((Handle)sidesRightH,(numSidesR)*sizeof(Side_List)); sideListForNode = (*sideListH)[nodeNum]; // Left Hand Side if (numSidesL ==0) { (*gDagTree.treeHdl)[branchNum].branchLeft = -8; // Fake a split if (sideListForNode.triLeft == -1) { strcpy(gErrStr,"Boundary not set up correctly - outside is on LHS"); goto done; } } else { // fTreeH in GNOME (a DAGHdl), member of fDagTree (part of GridVel, owned by the mover) (*gDagTree.treeHdl)[branchNum].branchLeft = gDagTree.numBranches; if(gErrStr[0]) goto done; // set call for correct area for sides nodeNum = newNodexx(sidesLeftH); MySpinCursor(); // JLM 8/4/99 split(sidesLeftH,nodeNum); // recursively for LHS //sidesLeftH = nil; // split disposed of this hdl } // Right Hand Side if (numSidesR == 0) { // Fake a split (*gDagTree.treeHdl)[branchNum].branchRight = -8; // place holder for steps in dag to all tri } else { (*gDagTree.treeHdl)[branchNum].branchRight = gDagTree.numBranches; if(gErrStr[0]) goto done; // set call for correct area for sides nodeNum = newNodexx(sidesRightH); split(sidesRightH,nodeNum); // recursively for RHS //sidesRightH = nil; // split disposed of this hdl } done: if(sidesRightH) DisposeHandle((Handle) sidesRightH); sidesRightH = nil; if(sidesLeftH) DisposeHandle((Handle) sidesLeftH); sidesLeftH = nil; return; }
OSErr ReadObjectInfo (short FRefNum, ObjectRecHdl *thisObjectHdlPtr) { OSErr ErrCode = 0; long byteCount, structSize; Handle thisObjectHdl = nil, thisObjectDataHdl = nil; // read the size of this object's info handle byteCount = sizeof (long); ErrCode = FSRead (FRefNum, &byteCount, (Ptr) &structSize); if (!ErrCode) { thisObjectHdl = _NewHandleClear (structSize); if (thisObjectHdl != nil) { _HLock (thisObjectHdl); ErrCode = FSRead (FRefNum, &structSize, (Ptr) *thisObjectHdl); _HUnlock (thisObjectHdl); } else ErrCode = memFullErr; } if (!ErrCode) // read the object's data handle if any { if (GetObjectDataHdl ((ObjectRecHdl) thisObjectHdl) != nil) { // read the size of this object's data handle byteCount = sizeof (long); ErrCode = FSRead (FRefNum, &byteCount, (Ptr) &structSize); if (!ErrCode) { thisObjectDataHdl = _NewHandleClear (structSize); if (thisObjectDataHdl != nil) { _HLock (thisObjectDataHdl); ErrCode = FSRead (FRefNum, &structSize, (Ptr) *thisObjectDataHdl); _HUnlock (thisObjectDataHdl); if (!ErrCode) SetObjectDataHdl ((ObjectRecHdl) thisObjectHdl, thisObjectDataHdl); } else ErrCode = memFullErr; } } } if (ErrCode) { if (thisObjectHdl != nil) DisposeHandle (thisObjectDataHdl); if (thisObjectHdl != nil) DisposeHandle (thisObjectDataHdl); } if (!ErrCode) *thisObjectHdlPtr = (ObjectRecHdl) thisObjectHdl; // send this handle back return (ErrCode); }
DAGTreeStruct MakeDagTree(TopologyHdl topoHdl, LongPoint **pointList, char *errStr) { Side_List **sidesList = 0; DAGTreeStruct dagTree; long numSidesInList; long nodeNum; // The index in the current side list for the node (segment) // to split across. strcpy(errStr,""); dagTree.treeHdl = 0; dagTree.numBranches = 0; sidesList=BuildSideList(topoHdl, errStr); //input checking if(sidesList == nil) { strcpy(errStr,"sideList is nil in MakeDagTree"); goto done; } LatLongTransform(pointList); gSidesList = sidesList; numSidesInList = (_GetHandleSize((Handle)sidesList))/(sizeof(Side_List)); if (numSidesInList < 3) { sprintf(errStr,"Triangles have 3 sides; the data has only %ld sides.", numSidesInList); goto done; } // make a better guess of size here gErrStr[0] = 0; gAllocatedDagLength = 2*numSidesInList; gDagTree.numBranches=0; gDagTree.treeHdl = (DAG**)_NewHandleClear(gAllocatedDagLength*sizeof(DAG)); if(!gDagTree.treeHdl) { strcpy(errStr,"Out of memory in MakeDagTree"); goto done; } srand(SEED); //srand(SEED+1); nodeNum = newNodexx(sidesList); split(sidesList, nodeNum); // Nothing should come back until DAG is completed. //gDagTree.numBranches--; // Had one too many increments in the split recursion. if(gErrStr[0]) { strcpy(errStr,gErrStr); gErrStr[0] = 0; if(gDagTree.treeHdl) DisposeHandle((Handle) gDagTree.treeHdl); gDagTree.treeHdl = nil; gDagTree.numBranches = 0; goto done; } ConvertSegNoToTopIndex(sidesList,gDagTree); dagTree = gDagTree; gDagTree.treeHdl = nil;// the handle is now their responsibility gDagTree.numBranches = 0; done: if(sidesList) { { DisposeHandle((Handle)sidesList); sidesList=0; } } return dagTree; }
OSErr NetCDFWindMoverCurv::ReadTimeData(long index,VelocityFH *velocityH, char* errmsg) { OSErr err = 0; long i,j; char path[256], outPath[256]; char *velUnits=0; int status, ncid, numdims; int wind_ucmp_id, wind_vcmp_id, angle_id, uv_ndims; static size_t wind_index[] = {0,0,0,0}, angle_index[] = {0,0}; static size_t wind_count[4], angle_count[2]; size_t velunit_len; float *wind_uvals = 0,*wind_vvals = 0, fill_value=-1e-72, velConversion=1.; short *wind_uvals_Navy = 0,*wind_vvals_Navy = 0, fill_value_Navy; float *angle_vals = 0; long totalNumberOfVels = fNumRows * fNumCols; VelocityFH velH = 0; long latlength = fNumRows; long lonlength = fNumCols; float scale_factor = 1.,angle = 0.,u_grid,v_grid; Boolean bRotated = true, fIsNavy = false, bIsNWSSpeedDirData = false; errmsg[0]=0; strcpy(path,fPathName); if (!path || !path[0]) return -1; status = nc_open(path, NC_NOWRITE, &ncid); //if (status != NC_NOERR) {err = -1; goto done;} if (status != NC_NOERR) { #if TARGET_API_MAC_CARBON err = ConvertTraditionalPathToUnixPath((const char *) path, outPath, kMaxNameLen) ; status = nc_open(outPath, NC_NOWRITE, &ncid); #endif if (status != NC_NOERR) {err = -1; goto done;} } status = nc_inq_ndims(ncid, &numdims); if (status != NC_NOERR) {err = -1; goto done;} wind_index[0] = index; // time wind_count[0] = 1; // take one at a time if (numdims>=4) // should check what the dimensions are, CO-OPS uses sigma { wind_count[1] = 1; // depth wind_count[2] = latlength; wind_count[3] = lonlength; } else { wind_count[1] = latlength; wind_count[2] = lonlength; } angle_count[0] = latlength; angle_count[1] = lonlength; //wind_count[0] = latlength; // a fudge for the PWS format which has u(lat,lon) not u(time,lat,lon) //wind_count[1] = lonlength; if (fIsNavy) { // need to check if type is float or short, if float no scale factor? wind_uvals = new float[latlength*lonlength]; if(!wind_uvals) {TechError("GridVel::ReadNetCDFFile()", "new[]", 0); err = memFullErr; goto done;} wind_vvals = new float[latlength*lonlength]; if(!wind_vvals) {TechError("GridVel::ReadNetCDFFile()", "new[]", 0); err = memFullErr; goto done;} angle_vals = new float[latlength*lonlength]; if(!angle_vals) {TechError("GridVel::ReadNetCDFFile()", "new[]", 0); err = memFullErr; goto done;} status = nc_inq_varid(ncid, "air_gridu", &wind_ucmp_id); if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_varid(ncid, "air_gridv", &wind_vcmp_id); if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_vara_float(ncid, wind_ucmp_id, wind_index, wind_count, wind_uvals); if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_vara_float(ncid, wind_vcmp_id, wind_index, wind_count, wind_vvals); if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_att_float(ncid, wind_ucmp_id, "_FillValue", &fill_value); //if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_att_float(ncid, wind_ucmp_id, "scale_factor", &scale_factor); //if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_varid(ncid, "grid_orient", &angle_id); if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_vara_float(ncid, angle_id, angle_index, angle_count, angle_vals); if (status != NC_NOERR) {/*err = -1; goto done;*/bRotated = false;} } else { wind_uvals = new float[latlength*lonlength]; if(!wind_uvals) {TechError("NetCDFWindMoverCurv::ReadTimeData()", "new[]", 0); err = memFullErr; goto done;} wind_vvals = new float[latlength*lonlength]; if(!wind_vvals) {TechError("NetCDFWindMoverCurv::ReadTimeData()", "new[]", 0); err = memFullErr; goto done;} status = nc_inq_varid(ncid, "air_u", &wind_ucmp_id); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "u", &wind_ucmp_id); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "U", &wind_ucmp_id); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "WindSpd_SFC", &wind_ucmp_id); if (status != NC_NOERR) {err = -1; goto done;} bIsNWSSpeedDirData = true; } //{err = -1; goto done;} } //{err = -1; goto done;} } if (bIsNWSSpeedDirData) { status = nc_inq_varid(ncid, "WindDir_SFC", &wind_vcmp_id); if (status != NC_NOERR) {err = -2; goto done;} } else { status = nc_inq_varid(ncid, "air_v", &wind_vcmp_id); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "v", &wind_vcmp_id); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "V", &wind_vcmp_id); if (status != NC_NOERR) {err = -1; goto done;} } //{err = -1; goto done;} } } status = nc_inq_varndims(ncid, wind_ucmp_id, &uv_ndims); if (status==NC_NOERR){if (uv_ndims < numdims && uv_ndims==3) {wind_count[1] = latlength; wind_count[2] = lonlength;}} // could have more dimensions than are used in u,v status = nc_get_vara_float(ncid, wind_ucmp_id, wind_index, wind_count, wind_uvals); if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_vara_float(ncid, wind_vcmp_id, wind_index, wind_count, wind_vvals); if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_att_float(ncid, wind_ucmp_id, "_FillValue", &fill_value); if (status != NC_NOERR) { status = nc_get_att_float(ncid, wind_ucmp_id, "Fill_Value", &fill_value); if (status != NC_NOERR) { status = nc_get_att_float(ncid, wind_ucmp_id, "fillValue", &fill_value);// nws 2.5km if (status != NC_NOERR) { status = nc_get_att_float(ncid, wind_ucmp_id, "missing_value", &fill_value); } /*if (status != NC_NOERR)*//*err = -1; goto done;*/}} // don't require //if (status != NC_NOERR) {err = -1; goto done;} // don't require } status = nc_inq_attlen(ncid, wind_ucmp_id, "units", &velunit_len); if (status == NC_NOERR) { velUnits = new char[velunit_len+1]; status = nc_get_att_text(ncid, wind_ucmp_id, "units", velUnits); if (status == NC_NOERR) { velUnits[velunit_len] = '\0'; if (!strcmpnocase(velUnits,"knots")) velConversion = KNOTSTOMETERSPERSEC; else if (!strcmpnocase(velUnits,"m/s")) velConversion = 1.0; } } status = nc_close(ncid); if (status != NC_NOERR) {err = -1; goto done;} velH = (VelocityFH)_NewHandleClear(totalNumberOfVels * sizeof(VelocityFRec)); if (!velH) {err = memFullErr; goto done;} //for (i=0;i<totalNumberOfVels;i++) for (i=0;i<latlength;i++) { for (j=0;j<lonlength;j++) { if (wind_uvals[(latlength-i-1)*lonlength+j]==fill_value) wind_uvals[(latlength-i-1)*lonlength+j]=0.; if (wind_vvals[(latlength-i-1)*lonlength+j]==fill_value) wind_vvals[(latlength-i-1)*lonlength+j]=0.; if (isnan(wind_uvals[(latlength-i-1)*lonlength+j])) wind_uvals[(latlength-i-1)*lonlength+j]=0.; if (isnan(wind_vvals[(latlength-i-1)*lonlength+j])) wind_vvals[(latlength-i-1)*lonlength+j]=0.; if (fIsNavy) { u_grid = (float)wind_uvals[(latlength-i-1)*lonlength+j]; v_grid = (float)wind_vvals[(latlength-i-1)*lonlength+j]; if (bRotated) angle = angle_vals[(latlength-i-1)*lonlength+j]; INDEXH(velH,i*lonlength+j).u = u_grid*cos(angle*PI/180.)-v_grid*sin(angle*PI/180.); INDEXH(velH,i*lonlength+j).v = u_grid*sin(angle*PI/180.)+v_grid*cos(angle*PI/180.); } else if (bIsNWSSpeedDirData) { //INDEXH(velH,i*lonlength+j).u = KNOTSTOMETERSPERSEC * wind_uvals[(latlength-i-1)*lonlength+j] * sin ((PI/180.) * wind_vvals[(latlength-i-1)*lonlength+j]); // need units //INDEXH(velH,i*lonlength+j).v = KNOTSTOMETERSPERSEC * wind_uvals[(latlength-i-1)*lonlength+j] * cos ((PI/180.) * wind_vvals[(latlength-i-1)*lonlength+j]); // since direction is from rather than to need to switch the sign //INDEXH(velH,i*lonlength+j).u = -1. * KNOTSTOMETERSPERSEC * wind_uvals[(latlength-i-1)*lonlength+j] * sin ((PI/180.) * wind_vvals[(latlength-i-1)*lonlength+j]); // need units //INDEXH(velH,i*lonlength+j).v = -1. * KNOTSTOMETERSPERSEC * wind_uvals[(latlength-i-1)*lonlength+j] * cos ((PI/180.) * wind_vvals[(latlength-i-1)*lonlength+j]); INDEXH(velH,i*lonlength+j).u = -1. * velConversion * wind_uvals[(latlength-i-1)*lonlength+j] * sin ((PI/180.) * wind_vvals[(latlength-i-1)*lonlength+j]); // need units INDEXH(velH,i*lonlength+j).v = -1. * velConversion * wind_uvals[(latlength-i-1)*lonlength+j] * cos ((PI/180.) * wind_vvals[(latlength-i-1)*lonlength+j]); } else { // Look for a land mask, but do this if don't find one - float mask(lat,lon) - 1,0 which is which? //if (wind_uvals[(latlength-i-1)*lonlength+j]==0. && wind_vvals[(latlength-i-1)*lonlength+j]==0.) //wind_uvals[(latlength-i-1)*lonlength+j] = wind_vvals[(latlength-i-1)*lonlength+j] = 1e-06; // just leave fillValue as velocity for new algorithm - comment following lines out // should eliminate the above problem, assuming fill_value is a land mask // leave for now since not using a map...use the entire grid ///////////////////////////////////////////////// INDEXH(velH,i*lonlength+j).u = /*KNOTSTOMETERSPERSEC**/velConversion*wind_uvals[(latlength-i-1)*lonlength+j]; // need units INDEXH(velH,i*lonlength+j).v = /*KNOTSTOMETERSPERSEC**/velConversion*wind_vvals[(latlength-i-1)*lonlength+j]; } } } *velocityH = velH; fFillValue = fill_value; fWindScale = scale_factor; // hmm, this forces a reset of scale factor each time, overriding any set by hand done: if (err) { if (err==-2) strcpy(errmsg,"Error reading wind data from NetCDF file"); else strcpy(errmsg,"Error reading wind direction data from NetCDF file"); // We don't want to put up an error message here because it can lead to an infinite loop of messages. //printNote("Error opening NetCDF file"); if(velH) {DisposeHandle((Handle)velH); velH = 0;} } if (wind_uvals) {delete [] wind_uvals; wind_uvals = 0;} if (wind_vvals) {delete [] wind_vvals; wind_vvals = 0;} if (angle_vals) {delete [] angle_vals; angle_vals = 0;} return err; }
OSErr NetCDFWindMoverCurv::TextRead(char *path, TMap **newMap, char *topFilePath) // don't want a map { // this code is for curvilinear grids OSErr err = 0; long i,j, numScanned, indexOfStart = 0; int status, ncid, latIndexid, lonIndexid, latid, lonid, recid, timeid, numdims; size_t latLength, lonLength, recs, t_len, t_len2; float timeVal; char recname[NC_MAX_NAME], *timeUnits=0, month[10]; char dimname[NC_MAX_NAME], s[256], topPath[256]; WORLDPOINTFH vertexPtsH=0; float *lat_vals=0,*lon_vals=0,yearShift=0.; static size_t timeIndex,ptIndex[2]={0,0}; static size_t pt_count[2]; Seconds startTime, startTime2; double timeConversion = 1.; char errmsg[256] = "",className[256]=""; char fileName[64],*modelTypeStr=0; Point where; OSType typeList[] = { 'NULL', 'NULL', 'NULL', 'NULL' }; MySFReply reply; Boolean bTopFile = false, fIsNavy = false; // for now keep code around but probably don't need Navy curvilinear wind //VelocityFH velocityH = 0; char outPath[256]; if (!path || !path[0]) return 0; strcpy(fPathName,path); strcpy(s,path); SplitPathFile (s, fileName); strcpy(fFileName, fileName); // maybe use a name from the file status = nc_open(path, NC_NOWRITE, &ncid); //if (status != NC_NOERR) {err = -1; goto done;} if (status != NC_NOERR) { #if TARGET_API_MAC_CARBON err = ConvertTraditionalPathToUnixPath((const char *) path, outPath, kMaxNameLen) ; status = nc_open(outPath, NC_NOWRITE, &ncid); #endif if (status != NC_NOERR) {err = -1; goto done;} } // check number of dimensions - 2D or 3D status = nc_inq_ndims(ncid, &numdims); if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_attlen(ncid,NC_GLOBAL,"generating_model",&t_len2); if (status != NC_NOERR) {fIsNavy = false; /*goto done;*/} else { fIsNavy = true; // may only need to see keyword is there, since already checked grid type modelTypeStr = new char[t_len2+1]; status = nc_get_att_text(ncid, NC_GLOBAL, "generating_model", modelTypeStr); if (status != NC_NOERR) {fIsNavy = false; goto done;} modelTypeStr[t_len2] = '\0'; strcpy(fFileName, modelTypeStr); } GetClassName(className); if (!strcmp("NetCDF Wind",className)) SetClassName(fFileName); //first check that name is now the default and not set by command file ("NetCDF Wind") //if (fIsNavy) { status = nc_inq_dimid(ncid, "time", &recid); //Navy //if (status != NC_NOERR) {err = -1; goto done;} if (status != NC_NOERR) { status = nc_inq_unlimdim(ncid, &recid); // issue of time not being unlimited dimension if (status != NC_NOERR) {err = -1; goto done;} } } /*else { status = nc_inq_unlimdim(ncid, &recid); // issue of time not being unlimited dimension if (status != NC_NOERR) {err = -1; goto done;} }*/ //if (fIsNavy) status = nc_inq_varid(ncid, "time", &timeid); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "ProjectionHr", &timeid); if (status != NC_NOERR) {err = -1; goto done;} } // if (status != NC_NOERR) {/*err = -1; goto done;*/timeid=recid;} //if (!fIsNavy) //status = nc_inq_attlen(ncid, recid, "units", &t_len); // recid is the dimension id not the variable id //else // LAS has them in order, and time is unlimited, but variable/dimension names keep changing so leave this way for now status = nc_inq_attlen(ncid, timeid, "units", &t_len); if (status != NC_NOERR) { timeUnits = 0; // files should always have this info timeConversion = 3600.; // default is hours startTime2 = model->GetStartTime(); // default to model start time //err = -1; goto done; } else { DateTimeRec time; char unitStr[24], junk[10]; timeUnits = new char[t_len+1]; //if (!fIsNavy) //status = nc_get_att_text(ncid, recid, "units", timeUnits); // recid is the dimension id not the variable id //else status = nc_get_att_text(ncid, timeid, "units", timeUnits); if (status != NC_NOERR) {err = -1; goto done;} timeUnits[t_len] = '\0'; // moved this statement before StringSubstitute, JLM 5/2/10 StringSubstitute(timeUnits, ':', ' '); StringSubstitute(timeUnits, '-', ' '); StringSubstitute(timeUnits, 'T', ' '); StringSubstitute(timeUnits, 'Z', ' '); numScanned=sscanf(timeUnits, "%s %s %hd %hd %hd %hd %hd %hd", unitStr, junk, &time.year, &time.month, &time.day, &time.hour, &time.minute, &time.second) ; if (numScanned==5) {time.hour = 0; time.minute = 0; time.second = 0; } else if (numScanned==7) // has two extra time entries ?? time.second = 0; else if (numScanned<8) //else if (numScanned!=8) { //timeUnits = 0; // files should always have this info //timeConversion = 3600.; // default is hours //startTime2 = model->GetStartTime(); // default to model start time err = -1; TechError("NetCDFWindMoverCurv::TextRead()", "sscanf() == 8", 0); goto done; } else { // code goes here, trouble with the DAYS since 1900 format, since converts to seconds since 1904 if (time.year ==1900) {time.year += 40; time.day += 1; /*for the 1900 non-leap yr issue*/ yearShift = 40.;} DateToSeconds (&time, &startTime2); // code goes here, which start Time to use ?? if (!strcmpnocase(unitStr,"HOURS") || !strcmpnocase(unitStr,"HOUR")) timeConversion = 3600.; else if (!strcmpnocase(unitStr,"MINUTES") || !strcmpnocase(unitStr,"MINUTE")) timeConversion = 60.; else if (!strcmpnocase(unitStr,"SECONDS") || !strcmpnocase(unitStr,"SECOND")) timeConversion = 1.; else if (!strcmpnocase(unitStr,"DAYS") || !strcmpnocase(unitStr,"DAY")) timeConversion = 24.*3600.; } } status = nc_inq_dimid(ncid, "yc", &latIndexid); if (status != NC_NOERR) { status = nc_inq_dimid(ncid, "y", &latIndexid); if (status != NC_NOERR) { err = -1; goto OLD; } } bIsCOOPSWaterMask = true; status = nc_inq_varid(ncid, "latc", &latid); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "lat", &latid); if (status != NC_NOERR) { err = -1; goto done; } } status = nc_inq_dimlen(ncid, latIndexid, &latLength); if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_dimid(ncid, "xc", &lonIndexid); if (status != NC_NOERR) { status = nc_inq_dimid(ncid, "x", &lonIndexid); if (status != NC_NOERR) { err = -1; goto done; } } status = nc_inq_varid(ncid, "lonc", &lonid); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "lon", &lonid); if (status != NC_NOERR) { err = -1; goto done; } } status = nc_inq_dimlen(ncid, lonIndexid, &lonLength); if (status != NC_NOERR) {err = -1; goto done;} OLD: if (!bIsCOOPSWaterMask) { if (fIsNavy) { status = nc_inq_dimid(ncid, "gridy", &latIndexid); //Navy if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_dimlen(ncid, latIndexid, &latLength); if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_dimid(ncid, "gridx", &lonIndexid); //Navy if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_dimlen(ncid, lonIndexid, &lonLength); if (status != NC_NOERR) {err = -1; goto done;} // option to use index values? status = nc_inq_varid(ncid, "grid_lat", &latid); if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_varid(ncid, "grid_lon", &lonid); if (status != NC_NOERR) {err = -1; goto done;} } else { for (i=0;i<numdims;i++) { if (i == recid) continue; status = nc_inq_dimname(ncid,i,dimname); if (status != NC_NOERR) {err = -1; goto done;} if (!strncmpnocase(dimname,"X",1) || !strncmpnocase(dimname,"LON",3) || !strncmpnocase(dimname,"nx",2)) { lonIndexid = i; } if (!strncmpnocase(dimname,"Y",1) || !strncmpnocase(dimname,"LAT",3) || !strncmpnocase(dimname,"ny",2)) { latIndexid = i; } } status = nc_inq_dimlen(ncid, latIndexid, &latLength); if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_dimlen(ncid, lonIndexid, &lonLength); if (status != NC_NOERR) {err = -1; goto done;} status = nc_inq_varid(ncid, "LATITUDE", &latid); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "lat", &latid); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "latitude", &latid); if (status != NC_NOERR) {err = -1; goto done;} } } status = nc_inq_varid(ncid, "LONGITUDE", &lonid); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "lon", &lonid); if (status != NC_NOERR) { status = nc_inq_varid(ncid, "longitude", &lonid); if (status != NC_NOERR) {err = -1; goto done;} } } } } pt_count[0] = latLength; pt_count[1] = lonLength; vertexPtsH = (WorldPointF**)_NewHandleClear(latLength*lonLength*sizeof(WorldPointF)); if (!vertexPtsH) {err = memFullErr; goto done;} lat_vals = new float[latLength*lonLength]; lon_vals = new float[latLength*lonLength]; if (!lat_vals || !lon_vals) {err = memFullErr; goto done;} status = nc_get_vara_float(ncid, latid, ptIndex, pt_count, lat_vals); if (status != NC_NOERR) {err = -1; goto done;} status = nc_get_vara_float(ncid, lonid, ptIndex, pt_count, lon_vals); if (status != NC_NOERR) {err = -1; goto done;} for (i=0;i<latLength;i++) { for (j=0;j<lonLength;j++) { //if (lat_vals[(latLength-i-1)*lonLength+j]==fill_value) // this would be an error //lat_vals[(latLength-i-1)*lonLength+j]=0.; //if (lon_vals[(latLength-i-1)*lonLength+j]==fill_value) //lon_vals[(latLength-i-1)*lonLength+j]=0.; INDEXH(vertexPtsH,i*lonLength+j).pLat = lat_vals[(latLength-i-1)*lonLength+j]; INDEXH(vertexPtsH,i*lonLength+j).pLong = lon_vals[(latLength-i-1)*lonLength+j]; } } fVertexPtsH = vertexPtsH; status = nc_inq_dim(ncid, recid, recname, &recs); if (status != NC_NOERR) {err = -1; goto done;} if (recs<=0) {strcpy(errmsg,"No times in file. Error opening NetCDF wind file"); err = -1; goto done;} fTimeHdl = (Seconds**)_NewHandleClear(recs*sizeof(Seconds)); if (!fTimeHdl) {err = memFullErr; goto done;} for (i=0;i<recs;i++) { Seconds newTime; // possible units are, HOURS, MINUTES, SECONDS,... timeIndex = i; //if (!fIsNavy) //status = nc_get_var1_float(ncid, recid, &timeIndex, &timeVal); // recid is the dimension id not the variable id //else status = nc_get_var1_float(ncid, timeid, &timeIndex, &timeVal); if (status != NC_NOERR) {err = -1; goto done;} newTime = RoundDateSeconds(round(startTime2+timeVal*timeConversion)); //INDEXH(fTimeHdl,i) = startTime2+(long)(timeVal*timeConversion -yearShift*3600.*24.*365.25); // which start time where? //if (i==0) startTime = startTime2+(long)(timeVal*timeConversion -yearShift*3600.*24.*365.25); INDEXH(fTimeHdl,i) = newTime-yearShift*3600.*24.*365.25; // which start time where? if (i==0) startTime = newTime-yearShift*3600.*24.*365.25; } if (model->GetStartTime() != startTime || model->GetModelTime()!=model->GetStartTime()) { if (true) // maybe use NOAA.ver here? { short buttonSelected; //buttonSelected = MULTICHOICEALERT(1688,"Do you want to reset the model start time to the first time in the file?",FALSE); if(!gCommandFileRun) // also may want to skip for location files... buttonSelected = MULTICHOICEALERT(1688,"Do you want to reset the model start time to the first time in the file?",FALSE); else buttonSelected = 1; // TAP user doesn't want to see any dialogs, always reset (or maybe never reset? or send message to errorlog?) switch(buttonSelected){ case 1: // reset model start time //bTopFile = true; model->SetModelTime(startTime); model->SetStartTime(startTime); model->NewDirtNotification(DIRTY_RUNBAR); // must reset the runbar break; case 3: // don't reset model start time //bTopFile = false; break; case 4: // cancel err=-1;// user cancel goto done; } } //model->SetModelTime(startTime); //model->SetStartTime(startTime); //model->NewDirtNotification(DIRTY_RUNBAR); // must reset the runbar } fNumRows = latLength; fNumCols = lonLength; status = nc_close(ncid); if (status != NC_NOERR) {err = -1; goto done;} //err = this -> SetInterval(errmsg); //if(err) goto done; // look for topology in the file // for now ask for an ascii file, output from Topology save option // need dialog to ask for file //if (fIsNavy) // for now don't allow for wind files {if (topFilePath[0]) {err = ReadTopology(topFilePath,newMap); goto done;}} if (!gCommandFileRun) { short buttonSelected; buttonSelected = MULTICHOICEALERT(1688,"Do you have an extended topology file to load?",FALSE); switch(buttonSelected){ case 1: // there is an extended top file bTopFile = true; break; case 3: // no extended top file bTopFile = false; break; case 4: // cancel err=-1;// stay at this dialog goto done; } } if(bTopFile) { #if TARGET_API_MAC_CARBON mysfpgetfile(&where, "", -1, typeList, (MyDlgHookUPP)0, &reply, M38c, MakeModalFilterUPP(STDFilter)); if (!reply.good)/* return USERCANCEL;*/ { /*if (recs>0) err = this -> ReadTimeData(indexOfStart,&velocityH,errmsg); else {strcpy(errmsg,"No times in file. Error opening NetCDF file"); err = -1;} if(err) goto done;*/ if (bIsCOOPSWaterMask) err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPointsCOOPSNoMask(newMap,errmsg); else err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPoints(newMap,errmsg); //err = ReorderPoints(fStartData.dataHdl,newMap,errmsg); // if u, v input separately only do this once? goto done; } else strcpy(topPath, reply.fullPath); #else where = CenteredDialogUpLeft(M38c); sfpgetfile(&where, "", (FileFilterUPP)0, -1, typeList, (DlgHookUPP)0, &reply, M38c, (ModalFilterUPP)MakeUPP((ProcPtr)STDFilter, uppModalFilterProcInfo)); if (!reply.good) { /*if (recs>0) err = this -> ReadTimeData(indexOfStart,&velocityH,errmsg); else {strcpy(errmsg,"No times in file. Error opening NetCDF file"); err = -1;} if(err) goto done;*/ if (bIsCOOPSWaterMask) err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPointsCOOPSNoMask(newMap,errmsg); else err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPoints(newMap,errmsg); //err = ReorderPoints(fStartData.dataHdl,newMap,errmsg); /*if (err)*/ goto done; } my_p2cstr(reply.fName); #ifdef MAC GetFullPath(reply.vRefNum, 0, (char *)reply.fName, topPath); #else strcpy(topPath, reply.fName); #endif #endif strcpy (s, topPath); err = ReadTopology(topPath,newMap); goto done; } /*if (recs>0) err = this -> ReadTimeData(indexOfStart,&velocityH,errmsg); else {strcpy(errmsg,"No times in file. Error opening NetCDF wind file"); err = -1;} if(err) goto done;*/ if (bIsCOOPSWaterMask) err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPointsCOOPSNoMask(newMap,errmsg); else err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPoints(newMap,errmsg); //err = ReorderPoints(fStartData.dataHdl,newMap,errmsg); done: if (err) { printNote("Error opening NetCDF wind file"); if(fGrid) { fGrid ->Dispose(); delete fGrid; fGrid = 0; } if(vertexPtsH) {DisposeHandle((Handle)vertexPtsH); vertexPtsH = 0; fVertexPtsH = 0;} } if (timeUnits) delete [] timeUnits; if (lat_vals) delete [] lat_vals; if (lon_vals) delete [] lon_vals; if (modelTypeStr) delete [] modelTypeStr; //if (velocityH) {DisposeHandle((Handle)velocityH); velocityH = 0;} return err; }
// simplify for wind data - no map needed, no mask OSErr NetCDFWindMoverCurv_c::ReorderPoints(TMap **newMap, char* errmsg) { long i, j, n, ntri, numVerdatPts=0; long fNumRows_ext = fNumRows+1, fNumCols_ext = fNumCols+1; long nv = fNumRows * fNumCols, nv_ext = fNumRows_ext*fNumCols_ext; long iIndex, jIndex, index; long triIndex1, triIndex2, waterCellNum=0; long ptIndex = 0, cellNum = 0; long indexOfStart = 0; OSErr err = 0; LONGH landWaterInfo = (LONGH)_NewHandleClear(fNumRows * fNumCols * sizeof(long)); LONGH maskH2 = (LONGH)_NewHandleClear(nv_ext * sizeof(long)); LONGH ptIndexHdl = (LONGH)_NewHandleClear(nv_ext * sizeof(**ptIndexHdl)); LONGH verdatPtsH = (LONGH)_NewHandleClear(nv_ext * sizeof(**verdatPtsH)); GridCellInfoHdl gridCellInfo = (GridCellInfoHdl)_NewHandleClear(nv * sizeof(**gridCellInfo)); TopologyHdl topo=0; LongPointHdl pts=0; VelocityFH velH = 0; DAGTreeStruct tree; WorldRect triBounds; TTriGridVel *triGrid = nil; tree.treeHdl = 0; TDagTree *dagTree = 0; VelocityFH velocityH = 0; if (!landWaterInfo || !ptIndexHdl || !gridCellInfo || !verdatPtsH || !maskH2) {err = memFullErr; goto done;} err = ReadTimeData(indexOfStart,&velocityH,errmsg); // try to use velocities to set grid for (i=0;i<fNumRows;i++) { for (j=0;j<fNumCols;j++) { // eventually will need to have a land mask, for now assume fillValue represents land //if (INDEXH(velocityH,i*fNumCols+j).u==0 && INDEXH(velocityH,i*fNumCols+j).v==0) // land point if (INDEXH(velocityH,i*fNumCols+j).u==fFillValue && INDEXH(velocityH,i*fNumCols+j).v==fFillValue) // land point { INDEXH(landWaterInfo,i*fNumCols+j) = -1; // may want to mark each separate island with a unique number } else { INDEXH(landWaterInfo,i*fNumCols+j) = 1; INDEXH(ptIndexHdl,i*fNumCols_ext+j) = -2; // water box INDEXH(ptIndexHdl,i*fNumCols_ext+j+1) = -2; INDEXH(ptIndexHdl,(i+1)*fNumCols_ext+j) = -2; INDEXH(ptIndexHdl,(i+1)*fNumCols_ext+j+1) = -2; } } } for (i=0;i<fNumRows_ext;i++) { for (j=0;j<fNumCols_ext;j++) { if (INDEXH(ptIndexHdl,i*fNumCols_ext+j) == -2) { INDEXH(ptIndexHdl,i*fNumCols_ext+j) = ptIndex; // count up grid points ptIndex++; } else INDEXH(ptIndexHdl,i*fNumCols_ext+j) = -1; } } for (i=0;i<fNumRows;i++) { for (j=0;j<fNumCols;j++) { if (INDEXH(landWaterInfo,i*fNumCols+j)>0) { INDEXH(gridCellInfo,i*fNumCols+j).cellNum = cellNum; cellNum++; INDEXH(gridCellInfo,i*fNumCols+j).topLeft = INDEXH(ptIndexHdl,i*fNumCols_ext+j); INDEXH(gridCellInfo,i*fNumCols+j).topRight = INDEXH(ptIndexHdl,i*fNumCols_ext+j+1); INDEXH(gridCellInfo,i*fNumCols+j).bottomLeft = INDEXH(ptIndexHdl,(i+1)*fNumCols_ext+j); INDEXH(gridCellInfo,i*fNumCols+j).bottomRight = INDEXH(ptIndexHdl,(i+1)*fNumCols_ext+j+1); } else INDEXH(gridCellInfo,i*fNumCols+j).cellNum = -1; } } ntri = cellNum*2; // each water cell is split into two triangles if(!(topo = (TopologyHdl)_NewHandleClear(ntri * sizeof(Topology)))){err = memFullErr; goto done;} for (i=0;i<nv_ext;i++) { if (INDEXH(ptIndexHdl,i) != -1) { INDEXH(verdatPtsH,numVerdatPts) = i; //INDEXH(verdatPtsH,INDEXH(ptIndexHdl,i)) = i; numVerdatPts++; } } _SetHandleSize((Handle)verdatPtsH,numVerdatPts*sizeof(**verdatPtsH)); pts = (LongPointHdl)_NewHandle(sizeof(LongPoint)*(numVerdatPts)); if(pts == nil) { strcpy(errmsg,"Not enough memory to triangulate data."); return -1; } for (i=0; i<=numVerdatPts; i++) // make a list of grid points that will be used for triangles { float fLong, fLat, fDepth, dLon, dLat, dLon1, dLon2, dLat1, dLat2; //double val, u=0., v=0.; LongPoint vertex; if(i < numVerdatPts) { // since velocities are defined at the lower left corner of each grid cell // need to add an extra row/col at the top/right of the grid // set lat/lon based on distance between previous two points // these are just for boundary/drawing purposes, velocities are set to zero index = i+1; n = INDEXH(verdatPtsH,i); iIndex = n/fNumCols_ext; jIndex = n%fNumCols_ext; if (iIndex==0) { if (jIndex<fNumCols) { dLat = INDEXH(fVertexPtsH,fNumCols+jIndex).pLat - INDEXH(fVertexPtsH,jIndex).pLat; fLat = INDEXH(fVertexPtsH,jIndex).pLat - dLat; dLon = INDEXH(fVertexPtsH,fNumCols+jIndex).pLong - INDEXH(fVertexPtsH,jIndex).pLong; fLong = INDEXH(fVertexPtsH,jIndex).pLong - dLon; } else { dLat1 = (INDEXH(fVertexPtsH,jIndex-1).pLat - INDEXH(fVertexPtsH,jIndex-2).pLat); dLat2 = INDEXH(fVertexPtsH,fNumCols+jIndex-1).pLat - INDEXH(fVertexPtsH,fNumCols+jIndex-2).pLat; fLat = 2*(INDEXH(fVertexPtsH,jIndex-1).pLat + dLat1)-(INDEXH(fVertexPtsH,fNumCols+jIndex-1).pLat+dLat2); dLon1 = INDEXH(fVertexPtsH,fNumCols+jIndex-1).pLong - INDEXH(fVertexPtsH,jIndex-1).pLong; dLon2 = (INDEXH(fVertexPtsH,fNumCols+jIndex-2).pLong - INDEXH(fVertexPtsH,jIndex-2).pLong); fLong = 2*(INDEXH(fVertexPtsH,jIndex-1).pLong-dLon1)-(INDEXH(fVertexPtsH,jIndex-2).pLong-dLon2); } } else { if (jIndex<fNumCols) { fLat = INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex).pLat; fLong = INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex).pLong; //u = INDEXH(velocityH,(iIndex-1)*fNumCols+jIndex).u; //v = INDEXH(velocityH,(iIndex-1)*fNumCols+jIndex).v; } else { dLat = INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex-1).pLat - INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex-2).pLat; fLat = INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex-1).pLat + dLat; dLon = INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex-1).pLong - INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex-2).pLong; fLong = INDEXH(fVertexPtsH,(iIndex-1)*fNumCols+jIndex-1).pLong + dLon; } } vertex.v = (long)(fLat*1e6); vertex.h = (long)(fLong*1e6); fDepth = 1.; INDEXH(pts,i) = vertex; } else { // for outputting a verdat the last line should be all zeros index = 0; fLong = fLat = fDepth = 0.0; } ///////////////////////////////////////////////// } // figure out the bounds triBounds = voidWorldRect; if(pts) { LongPoint thisLPoint; if(numVerdatPts > 0) { WorldPoint wp; for(i=0;i<numVerdatPts;i++) { thisLPoint = INDEXH(pts,i); wp.pLat = thisLPoint.v; wp.pLong = thisLPoint.h; AddWPointToWRect(wp.pLat, wp.pLong, &triBounds); } } } DisplayMessage("NEXTMESSAGETEMP"); DisplayMessage("Making Triangles"); ///////////////////////////////////////////////// for (i=0;i<fNumRows;i++) { for (j=0;j<fNumCols;j++) { if (INDEXH(landWaterInfo,i*fNumCols+j)==-1) continue; waterCellNum = INDEXH(gridCellInfo,i*fNumCols+j).cellNum; // split each cell into 2 triangles triIndex1 = 2*waterCellNum; triIndex2 = 2*waterCellNum+1; // top/left tri in rect (*topo)[triIndex1].vertex1 = INDEXH(gridCellInfo,i*fNumCols+j).topRight; (*topo)[triIndex1].vertex2 = INDEXH(gridCellInfo,i*fNumCols+j).topLeft; (*topo)[triIndex1].vertex3 = INDEXH(gridCellInfo,i*fNumCols+j).bottomLeft; if (j==0 || INDEXH(gridCellInfo,i*fNumCols+j-1).cellNum == -1) (*topo)[triIndex1].adjTri1 = -1; else { (*topo)[triIndex1].adjTri1 = INDEXH(gridCellInfo,i*fNumCols+j-1).cellNum * 2 + 1; } (*topo)[triIndex1].adjTri2 = triIndex2; if (i==0 || INDEXH(gridCellInfo,(i-1)*fNumCols+j).cellNum==-1) (*topo)[triIndex1].adjTri3 = -1; else { (*topo)[triIndex1].adjTri3 = INDEXH(gridCellInfo,(i-1)*fNumCols+j).cellNum * 2 + 1; } // bottom/right tri in rect (*topo)[triIndex2].vertex1 = INDEXH(gridCellInfo,i*fNumCols+j).bottomLeft; (*topo)[triIndex2].vertex2 = INDEXH(gridCellInfo,i*fNumCols+j).bottomRight; (*topo)[triIndex2].vertex3 = INDEXH(gridCellInfo,i*fNumCols+j).topRight; if (j==fNumCols-1 || INDEXH(gridCellInfo,i*fNumCols+j+1).cellNum == -1) (*topo)[triIndex2].adjTri1 = -1; else { (*topo)[triIndex2].adjTri1 = INDEXH(gridCellInfo,i*fNumCols+j+1).cellNum * 2; } (*topo)[triIndex2].adjTri2 = triIndex1; if (i==fNumRows-1 || INDEXH(gridCellInfo,(i+1)*fNumCols+j).cellNum == -1) (*topo)[triIndex2].adjTri3 = -1; else { (*topo)[triIndex2].adjTri3 = INDEXH(gridCellInfo,(i+1)*fNumCols+j).cellNum * 2; } } } DisplayMessage("NEXTMESSAGETEMP"); DisplayMessage("Making Dag Tree"); MySpinCursor(); // JLM 8/4/99 tree = MakeDagTree(topo, (LongPoint**)pts, errmsg); MySpinCursor(); // JLM 8/4/99 if (errmsg[0]) {err = -1; goto done;} // sethandle size of the fTreeH to be tree.fNumBranches, the rest are zeros _SetHandleSize((Handle)tree.treeHdl,tree.numBranches*sizeof(DAG)); ///////////////////////////////////////////////// fVerdatToNetCDFH = verdatPtsH; ///////////////////////////////////////////////// triGrid = new TTriGridVel; if (!triGrid) { err = true; TechError("Error in NetCDFWindMoverCurv::ReorderPoints()","new TTriGridVel",err); goto done; } fGrid = (TTriGridVel*)triGrid; triGrid -> SetBounds(triBounds); dagTree = new TDagTree(pts,topo,tree.treeHdl,velH,tree.numBranches); if(!dagTree) { err = -1; printError("Unable to create dag tree."); goto done; } triGrid -> SetDagTree(dagTree); //triGrid -> SetDepths(totalDepthH); // used by PtCurMap to check vertical movement pts = 0; // because fGrid is now responsible for it topo = 0; // because fGrid is now responsible for it velH = 0; // because fGrid is now responsible for it tree.treeHdl = 0; // because fGrid is now responsible for it velH = 0; // because fGrid is now responsible for it ///////////////////////////////////////////////// done: if (landWaterInfo) {DisposeHandle((Handle)landWaterInfo); landWaterInfo=0;} if (ptIndexHdl) {DisposeHandle((Handle)ptIndexHdl); ptIndexHdl = 0;} if (gridCellInfo) {DisposeHandle((Handle)gridCellInfo); gridCellInfo = 0;} if(err) { if(!errmsg[0]) strcpy(errmsg,"An error occurred in NetCDFWindMoverCurv::ReorderPoints"); printError(errmsg); if(pts) {DisposeHandle((Handle)pts); pts=0;} if(topo) {DisposeHandle((Handle)topo); topo=0;} if(velH) {DisposeHandle((Handle)velH); velH=0;} if(tree.treeHdl) {DisposeHandle((Handle)tree.treeHdl); tree.treeHdl=0;} if(fGrid) { fGrid ->Dispose(); delete fGrid; fGrid = 0; } if (verdatPtsH) {DisposeHandle((Handle)verdatPtsH); verdatPtsH = 0;} if (maskH2) {DisposeHandle((Handle)maskH2); maskH2 = 0;} } if (velocityH) {DisposeHandle((Handle)velocityH); velocityH = 0;} return err; }
OSErr ComponentMover_c::CalculateAveragedWindsHdl(char *errmsg) { OSErr err = 0; long i, j, numTimeSteps = (model -> GetEndTime () - model -> GetStartTime ()) / model -> GetTimeStep() + 1; VelocityRec value, avValue; TMover *mover; VelocityRec wVel = {0.,0.}; Boolean bFound = false; double pat1Theta = PI * -(0.5 + (pat1Angle / 180.0)); double pat2Theta = PI * -(0.5 + (pat2Angle / 180.0)); WorldPoint3D refPoint3D = {0,0,0.}; VelocityRec pat1ValRef; double pat1ValRefLength; refPoint3D.p = refP; pat1ValRef = pattern1 -> GetPatValue (refPoint3D); pat1ValRefLength = sqrt (pat1ValRef.u * pat1ValRef.u + pat1ValRef.v * pat1ValRef.v); strcpy(errmsg,""); // calculate handle size - number of time steps, end time - start time / time step + 1 // for each time step, start at 24 hrs (or whatever) before and average wind at each step up to current // if no values that far back give an error // put time and value in the handle // if error delete // code goes here, might want to extend handle if model run time is changed, or recreate? // then should delete handle in case it still exists... if (fAveragedWindsHdl) { // should dispose at end of run?? DisposeHandle((Handle)fAveragedWindsHdl); fAveragedWindsHdl = 0; } fAveragedWindsHdl = (TimeValuePairH)_NewHandleClear(sizeof(TimeValuePair)*numTimeSteps); if (!fAveragedWindsHdl) { TechError("TComponentMover::CalculateAveragedWindsHdl()", "_NewHandleClear()", 0); return -1; } // get the wind mover, if it's constant or nonexistent this is an error, should be checked in the dialog if (timeMoverCode == kLinkToWindMover) { long /* i, j,*/ m, n; // double length, theirLengthSq, myLengthSq, dotProduct; // VelocityRec theirVelocity,myVelocity; //VelocityRec wVel = {0.,0.}; TMap *map; // TMover *mover; // Boolean bFound = false; for (j = 0, m = model -> mapList -> GetItemCount() ; j < m && !bFound ; j++) { model -> mapList -> GetListItem((Ptr)&map, j); for (i = 0, n = map -> moverList -> GetItemCount() ; i < n ; i++) { map -> moverList -> GetListItem((Ptr)&mover, i); if (mover -> GetClassID() != TYPE_WINDMOVER) continue; if (!strcmp(mover -> className, windMoverName)) { // JLM, note: we are implicitly matching by file name above // ((TWindMover*) mover) -> GetTimeValue (model -> modelTime, &wVel); bFound = true; break; } } if (!bFound) { map = model -> uMap; for (i = 0, n = map -> moverList -> GetItemCount() ; i < n ; i++) { map -> moverList -> GetListItem((Ptr)&mover, i); if (mover -> GetClassID() != TYPE_WINDMOVER) continue; if (!strcmp(mover -> className, windMoverName)) { // JLM, note: we are implicitly matching by file name above //((TWindMover*) mover) -> GetTimeValue (model -> modelTime, &wVel); bFound = true; break; } } } } if (!bFound) { mover = (TMover*) (model->GetWindMover(false)); // see if there is a wind at all and use it if (!mover) { strcpy(windMoverName, ""); // clear out any value strcpy(errmsg,"There is no wind time file associated with the component mover"); //printError("There is no wind time file associated with the component mover"); return -1; } strcpy(windMoverName, mover->className); // link the wind to the component mover //print error, also check if it's a constant wind or times out of range } // alert code goes here if mover is not found } else { strcpy(errmsg,"There is no wind time file associated with the component mover"); // printError("There is no wind time file associated with the component mover"); return -1; } // check wind time file exists for whole length of run, including the past averaging hours for (i = 0 ; i < numTimeSteps ; i++) { long averageTimeSteps; double averageSpeed=0.,averageDir = 0; Seconds timeToGetAverageFor = model -> GetStartTime () + i * model -> GetTimeStep(); Seconds startPastTime = timeToGetAverageFor - fPastHoursToAverage * 3600; INDEXH(fAveragedWindsHdl, i).time = model -> GetStartTime () + i * model -> GetTimeStep(); //averageTimeSteps = fPastHoursToAverage+1; // for now, will change to match model time steps... averageTimeSteps = fPastHoursToAverage; // for now, will change to match model time steps... // code goes here, may want to change to GetStartTime, GetEndTime, then check out of range if (i==0) err = dynamic_cast<TWindMover *>(mover)->CheckStartTime(startPastTime); //if (forTime < INDEXH(timeValues, 0).time) if (err==-1) { if (bExtrapolateWinds) { // GetTimeValue() already extrapolates err = 0; } else { strcpy(errmsg,"There is not enough data in your wind file for the averaging"); goto done; } //printError("There is not enough data in your wind file for the averaging"); goto done; } if (err==-2) { //strcpy(errmsg,"No point in averaging for constant wind."); goto done; //fPastHoursToAverage=0; err=0; // allow constant wind, only need one value though //printError("No point in averaging for constant wind."); goto done; averageTimeSteps = 1; startPastTime = timeToGetAverageFor; // this doesn't really matter with constant wind err = 0; } //if (forTime > INDEXH(timeValues, n - 1).time) if (fPastHoursToAverage==0) averageTimeSteps = 1; // just use the straight wind for (j=0; j<averageTimeSteps; j++) { Seconds timeToAddToAverage = startPastTime + j*3600; // eventually this will be time step... double windSpeedToScale, windDir,theta; // get the time file / wind mover value for this time // get the mover first then repeat using it for the times..., but make sure get time value gets a value... // check first value - 24, last value else will just use first/last value // also check if it's not a time file... // make sure in the GetMove to GetTimeValue from the averaged handle // check here that time is in the handle... dynamic_cast<TWindMover *>(mover)-> GetTimeValue (timeToAddToAverage, &wVel); // minus AH 07/10/2012 //windSpeedToScale = sqrt(wVel.u*wVel.u + wVel.v*wVel.v); // code goes here, take the component first, then average ? windSpeedToScale = wVel.u * cos (pat1Theta) + wVel.v * sin (pat1Theta); //averageSpeed += (windSpeedToScale) * fScaleFactorAveragedWinds / pat1ValRefLength; //windSpeedToScale; //?? need the dot product too //averageSpeed += (windSpeedToScale); //windSpeedToScale; //?? need the dot product too - seems this was done twice? //windDir = fmod(atan2(wVel.u,wVel.v)*180/PI+360,360); // floating point remainder windDir = atan2(wVel.u,wVel.v); // //windDir = fmod(-180,360); // not sure what above does... //theta = fmod(theta+180,360); // rotate the vector cause wind is FROM this direction //r=sqrt(u*u+v*v); // windDir = 0; averageSpeed = averageSpeed + windSpeedToScale; // need to divide by averageTimeSteps averageDir = averageDir + windDir; //averageDir = averageDir + windSpeedToScale; // need to divide by averageTimeSteps // if add up wind dir make sure it's -180 to 180 - not necessary } averageSpeed = averageSpeed / averageTimeSteps; // apply power and scale - is this the right order? if (averageSpeed<0) averageSpeed = -1. * pow(myfabs(averageSpeed),fPowerFactorAveragedWinds); else /*if (fPowerFactorAveragedWinds!=1.)*/ averageSpeed = pow(averageSpeed,fPowerFactorAveragedWinds); //for now apply the scale factor in SetOptimizeVariables() //averageSpeed = averageSpeed*fScaleFactorAveragedWinds; // code goes here bUseMainDialogScaleFactor = true do this way leave out fSFAW, = false just use fSFAW averageDir = averageDir / averageTimeSteps; //avValue.u = averageSpeed*sin(averageDir/*+PI*/); // not sure about the pi //avValue.v = averageSpeed*cos(averageDir/*+PI*/); avValue.u = averageSpeed; // not sure about the pi avValue.v = 0; // not sure about the pi INDEXH(fAveragedWindsHdl, i).value = avValue;// translate back to u,v } done: if (err) { if (fAveragedWindsHdl) { // should dispose at end of run?? DisposeHandle((Handle)fAveragedWindsHdl); fAveragedWindsHdl = 0; } } return err; }
OSErr TriCurMover_c::ReadTimeData(long index,VelocityFH *velocityH, char* errmsg) { char s[256], path[256]; long i,j,line = 0; long offset,lengthToRead; CHARH h = 0; char *sectionOfFile = 0; char *strToMatch = 0; long len,numScanned; VelocityFH velH = 0; long totalNumberOfVels = 0; LongPointHdl ptsHdl = 0; //TopologyHdl topoH = GetTopologyHdl(); //TTriGridVel* triGrid = (TTriGridVel*)fGrid; OSErr err = 0; DateTimeRec time; Seconds timeSeconds; //long numPoints, numDepths; long numTris; errmsg[0]=0; strcpy(path,fVar.pathName); if (!path || !path[0]) return -1; lengthToRead = (*fTimeDataHdl)[index].lengthOfData; offset = (*fTimeDataHdl)[index].fileOffsetToStartOfData; if (fDepthDataInfo) numTris = _GetHandleSize((Handle)fDepthDataInfo)/sizeof(**fDepthDataInfo); //if(topoH) //numTris = _GetHandleSize((Handle)topoH)/sizeof(**topoH); else {err=-1; goto done;} // no data h = (CHARH)_NewHandle(lengthToRead+1); if(!h){TechError("TriCurMover::ReadTimeData()", "_NewHandle()", 0); err = memFullErr; goto done;} _HLock((Handle)h); sectionOfFile = *h; err = ReadSectionOfFile(0,0,path,offset,lengthToRead,sectionOfFile,0); if(err || !h) { char firstPartOfLine[128]; sprintf(errmsg,"Unable to open data file:%s",NEWLINESTRING); strncpy(firstPartOfLine,path,120); strcpy(firstPartOfLine+120,"..."); strcat(errmsg,firstPartOfLine); goto done; } sectionOfFile[lengthToRead] = 0; // make it a C string //numDepths = fVar.maxNumDepths; // for now we will always have a full set of velocities totalNumberOfVels = (*fDepthDataInfo)[numTris-1].indexToDepthData+(*fDepthDataInfo)[numTris-1].numDepths; //totalNumberOfVels = numTris*numDepths; if(totalNumberOfVels<numTris) {err=-1; goto done;} // must have at least full set of 2D velocity data velH = (VelocityFH)_NewHandleClear(sizeof(**velH)*totalNumberOfVels); if(!velH){TechError("TriCurMover::ReadTimeData()", "_NewHandle()", 0); err = memFullErr; goto done;} strToMatch = "[TIME]"; len = strlen(strToMatch); NthLineInTextOptimized (sectionOfFile, line = 0, s, 256); if(!strncmp(s,strToMatch,len)) { numScanned=sscanf(s+len, "%hd %hd %hd %hd %hd", &time.day, &time.month, &time.year, &time.hour, &time.minute) ; if (numScanned!= 5) { err = -1; TechError("TriCurMover::ReadTimeData()", "sscanf() == 5", 0); goto done; } // check for constant current if (time.day == -1 && time.month == -1 && time.year == -1 && time.hour == -1 && time.minute == -1) //if (time.year == time.month == time.day == time.hour == time.minute == -1) { timeSeconds = CONSTANTCURRENT; } else // time varying current { if (time.year < 1900) // two digit date, so fix it { if (time.year >= 40 && time.year <= 99) time.year += 1900; else time.year += 2000; // correct for year 2000 (00 to 40) } time.second = 0; DateToSeconds (&time, &timeSeconds); } // check time is correct if (timeSeconds!=(*fTimeDataHdl)[index].time) { err = -1; strcpy(errmsg,"Can't read data - times in the file have changed."); goto done; } line++; } for(i=0;i<numTris;i++) // interior points { VelocityRec vel; char *startScan; long scanLength,stringIndex=0; long numDepths = (*fDepthDataInfo)[i].numDepths; // allow for variable depths/velocites //long numDepths = fVar.maxNumDepths; char *s1 = new char[numDepths*64]; if(!s1) {TechError("TriCurMover::ReadTimeData()", "new[]", 0); err = memFullErr; goto done;} NthLineInTextOptimized (sectionOfFile, line, s1, numDepths*64); //might want to check that the number of lines matches the number of triangles (ie there is data at every triangle) startScan = &s1[stringIndex]; for(j=0;j<numDepths;j++) { err = ScanVelocity(startScan,&vel,&scanLength); // ScanVelocity is faster than scanf, but doesn't handle scientific notation. Try a scanf on error. if (err) { if(err!=-2 || sscanf(&s1[stringIndex],lfFix("%lf%lf"),&vel.u,&vel.v) < 2) { char firstPartOfLine[128]; sprintf(errmsg,"Unable to read velocity data from line %ld:%s",line,NEWLINESTRING); strncpy(firstPartOfLine,s1,120); strcpy(firstPartOfLine+120,"..."); strcat(errmsg,firstPartOfLine); delete[] s1; s1=0; goto done; } err = 0; } (*velH)[(*fDepthDataInfo)[i].indexToDepthData+j].u = vel.u; (*velH)[(*fDepthDataInfo)[i].indexToDepthData+j].v = vel.v; //(*velH)[i*numDepths+j].u = vel.u; //(*velH)[i*numDepths+j].v = vel.v; stringIndex += scanLength; startScan = &s1[stringIndex]; } line++; delete[] s1; s1=0; } *velocityH = velH; done: if(h) { _HUnlock((Handle)h); DisposeHandle((Handle)h); h = 0; } if(err) { if(!errmsg[0]) strcpy(errmsg,"An error occurred in TriCurMover::ReadTimeData"); //printError(errmsg); // This alert causes a freeze up... // We don't want to put up an error message here because it can lead to an infinite loop of messages. if(velH) {DisposeHandle((Handle)velH); velH = 0;} } return err; }