void DrawMapBoundsPoly (CMap* theMap, PolyObjectHdl MapPolyHdl, DrawSpecRecPtr drawSettings, Boolean erasePolygon) { long numPts = (**MapPolyHdl).pointCount; PolyHandle poly; LongPoint** thisPointsHdl=nil; Point pt,startPt; LongPoint wPt; long i; Boolean offQuickDrawPlane = false; RGBColor saveColor; // JLM ?? wouldn't compile without this GetForeColor (&saveColor); /* save original forecolor */ thisPointsHdl = (LongPoint**) (**MapPolyHdl).objectDataHdl; poly = OpenPoly(); wPt = INDEXH(thisPointsHdl,0); startPt = GetQuickDrawPt(wPt.h,wPt.v,&gRect,&offQuickDrawPlane); MyMoveTo(startPt.h,startPt.v); for(i = 1; i< numPts;i++) { wPt = INDEXH(thisPointsHdl,i); pt = GetQuickDrawPt(wPt.h,wPt.v,&gRect,&offQuickDrawPlane); MyLineTo(pt.h,pt.v); } MyLineTo(startPt.h,startPt.v); ClosePoly(); if (erasePolygon) ErasePoly(poly); FramePoly(poly); ErasePoly(poly); KillPoly(poly); RGBForeColor (&saveColor); }
OSErr InsertSegment(SEGMENTH *segments, long *numSegs, long index, WorldPoint m) { long i; if ((m.pLong == INDEXH(*segments, index).toLong && m.pLat == INDEXH(*segments, index).toLat) || (m.pLong == INDEXH(*segments, index).fromLong && m.pLat == INDEXH(*segments, index).fromLat)) return 0; _SetHandleSize((Handle)*segments, ((*numSegs) + 1) * sizeof(Segment)); if (_MemError()) { TechError("AddSegment()", "_SetHandleSize()", 0); return -1; } // old way: insert at end //INDEXH(*segments, *numSegs) = INDEXH(*segments, index); //INDEXH(*segments, index).toLong = m.pLong; //INDEXH(*segments, index).toLat = m.pLat; //INDEXH(*segments, *numSegs).fromLong = m.pLong; //INDEXH(*segments, *numSegs).fromLat = m.pLat; (*numSegs)++; // new way: insert as next segment for (i = (*numSegs) - 1 ; i > index ; i--) INDEXH(*segments, i) = INDEXH(*segments, i - 1); INDEXH(*segments, index).toLong = m.pLong; INDEXH(*segments, index).toLat = m.pLat; INDEXH(*segments, index + 1).fromLong = m.pLong; INDEXH(*segments, index + 1).fromLat = m.pLat; return 0; }
SEGMENTH WPointsToSegments(WORLDPOINTH wPoints, long numPoints, long *numSegs) { long i, j; SEGMENTH segments; if (EqualWPoints(INDEXH(wPoints, 0), INDEXH(wPoints, numPoints - 1))) (*numSegs) = numPoints - 1; else (*numSegs) = numPoints; segments = (SEGMENTH)_NewHandle((*numSegs) * sizeof(Segment)); if (_MemError()) { TechError("WPointsToSegments()", "_NewHandle()", 0); return 0; } for (i = 0 ; i < (*numSegs) ; i++) { INDEXH(segments, i).fromLong = INDEXH(wPoints, i).pLong; INDEXH(segments, i).fromLat = INDEXH(wPoints, i).pLat; if ((*numSegs) == numPoints && i == numPoints - 1) j = 0; else j = i + 1; INDEXH(segments, i).toLong = INDEXH(wPoints, j).pLong; INDEXH(segments, i).toLat = INDEXH(wPoints, j).pLat; } return segments; }
void LEList_c::RecalculateLEStatistics(long* numDispersed,long* numFloating,long* numRemoved,long* numOffMaps) { // code goes here, might want to calculate percent dissolved here long i; if (LEHandle) { for (i = 0 ; i < this->numOfLEs ; i++) { // code goes here, Alan occasionally seeing budget table floating < 0, maybe not released has z>0 or dispersed Le is getting beached? if( ((INDEXH(LEHandle, i).dispersionStatus == HAVE_DISPERSED || INDEXH(LEHandle, i).dispersionStatus == HAVE_DISPERSED_NAT) || INDEXH(LEHandle,i).z > 0) && !(INDEXH(LEHandle, i).statusCode==OILSTAT_EVAPORATED) && !(INDEXH(LEHandle, i).statusCode==OILSTAT_OFFMAPS) && !(INDEXH(LEHandle, i).statusCode==OILSTAT_NOTRELEASED) && !(INDEXH(LEHandle, i).statusCode==OILSTAT_ONLAND)) //if( ((INDEXH(LEHandle, i).dispersionStatus == HAVE_DISPERSED || INDEXH(LEHandle, i).dispersionStatus == HAVE_DISPERSED_NAT) || INDEXH(LEHandle,i).z > 0) && INDEXH(LEHandle, i).statusCode==OILSTAT_INWATER ) { (*numDispersed)++; (*numFloating)--; if ((*numFloating) < 0) { //printNote("Num floating < 0 in RecalculateLEStatistics"); } } if( (INDEXH(LEHandle, i).dispersionStatus == HAVE_REMOVED) && (INDEXH(LEHandle, i).statusCode==OILSTAT_OFFMAPS) ) { (*numRemoved)++; (*numOffMaps)--; if ((*numOffMaps) < 0) { printNote("Num off maps < 0 in RecalculateLEStatistics"); } } } } }
void DrawMapBoundsPoly (CMap* theMap, PolyObjectHdl MapPolyHdl, DrawSpecRecPtr drawSettings, Boolean erasePolygon) { long numPts = (**MapPolyHdl).pointCount; POINT **pointsH = (POINT**)_NewHandle(numPts *sizeof(POINT)); POINT *pointsPtr = (POINT*)_NewPtr(numPts *sizeof(POINT)); LongPoint** thisPointsHdl=nil; Point pt; LongPoint wPt; long i; Boolean offQuickDrawPlane = false; RGBColor saveColor; // JLM ?? wouldn't compile without this if(!pointsH || !pointsPtr) {SysBeep(5); return;} thisPointsHdl = (LongPoint**) (**MapPolyHdl).objectDataHdl; for(i = 0; i< numPts;i++) { wPt = INDEXH(thisPointsHdl,i); pt = GetQuickDrawPt(wPt.h,wPt.v,&gRect,&offQuickDrawPlane); INDEXH(pointsH,i) = MakePOINT(pt.h,pt.v); (pointsPtr)[i] = MakePOINT(pt.h,pt.v); // code goes here, make sure this point does not equal previous point JLM } GetForeColor (&saveColor); /* save original forecolor */ if (erasePolygon) { RgnHandle newClip=0; HBRUSH whiteBrush; newClip = CreatePolygonRgn((const POINT*)pointsPtr,numPts,ALTERNATE); whiteBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); //err = SelectClipRgn(currentHDC,savedClip); FillRgn(currentHDC, newClip, whiteBrush); //DeleteObject(newClip); DisposeRgn(newClip); //SelectClipRgn(currentHDC,0); } else { POINT p[2]; p[0] = INDEXH(pointsH,numPts-1); p[1] = INDEXH(pointsH,0); RGBForeColor(&colors[BLACK]); if(numPts >= 2) { Polyline(currentHDC,*pointsH,numPts); Polyline(currentHDC,p,2); // close the polygon } } RGBForeColor (&saveColor); DisposeHandle((Handle)pointsH); if(pointsPtr) {_DisposePtr((Ptr)pointsPtr); pointsPtr = 0;} }
void ResetMaskValues(LONGH maskH,long landBlockToMerge,long landBlockToJoin,long numRows,long numCols) { // merges adjoining land blocks and then renumbers any higher numbered land blocks long i,j,val; long numRows_ext = numRows+1, numCols_ext = numCols+1; for (i=0;i<numRows_ext;i++) { for (j=0;j<numCols_ext;j++) { val = INDEXH(maskH,i*numCols_ext+j); if (val==landBlockToMerge) INDEXH(maskH,i*numCols_ext+j) = landBlockToJoin; if (val>landBlockToMerge) INDEXH(maskH,i*numCols_ext+j) -= 1; } } }
Boolean ThereIsALowerLandNeighbor(LONGH maskH, long *lowerPolyNum, long numRows, long numCols, long row, long col) { long iStart, iEnd, jStart, jEnd, lowestLandIndex = 0; long i, j, neighbor, landPolyNum; long numRows_ext = numRows+1, numCols_ext = numCols+1; iStart = (row > 0) ? row - 1 : 0; jStart = (col > 0) ? col - 1 : 0; iEnd = (row < numRows_ext - 1) ? row + 1 : numRows_ext - 1; jEnd = (col < numCols_ext - 1) ? col + 1 : numCols_ext - 1; landPolyNum = INDEXH(maskH, row*numCols_ext + col); for (i = iStart; i< iEnd+1; i++) { if (i==row) continue; neighbor = INDEXH(maskH, i*numCols_ext + col); if (neighbor >= 3 && neighbor < landPolyNum) { *lowerPolyNum = neighbor; return true; } } for (j = jStart; j< jEnd+1; j++) { if (j==col) continue; neighbor = INDEXH(maskH, row*numCols_ext + j); if (neighbor >= 3 && neighbor < landPolyNum) { *lowerPolyNum = neighbor; return true; } } // don't allow diagonals for now, they could be separate small islands /*for (i = iStart; i< iEnd+1; i++) { for (j = jStart; j< jEnd+1; j++) { if (i==row && j==col) continue; neighbor = INDEXH(maskH, i*fNumCols_ext + j); if (neighbor >= 3 && neighbor < landPolyNum) { *lowerPolyNum = neighbor; return true; } } }*/ return false; }
VelocityRec RectGridVel_c::GetPatValue(WorldPoint p) { long rowNum, colNum; VelocityRec velocity; LongRect gridLRect, geoRect; ScaleRec thisScaleRec; SetLRect(&gridLRect, 0, fNumRows, fNumCols, 0); SetLRect(&geoRect, fGridBounds.loLong, fGridBounds.loLat, fGridBounds.hiLong, fGridBounds.hiLat); GetLScaleAndOffsets(&geoRect, &gridLRect, &thisScaleRec); // gridP = WorldToScreenPoint(p, bounds, CATSgridRect); colNum = (long)(p.pLong * thisScaleRec.XScale + thisScaleRec.XOffset); rowNum = (long)(p.pLat * thisScaleRec.YScale + thisScaleRec.YOffset); if (!fGridHdl || colNum < 0 || colNum >= fNumCols || rowNum < 0 || rowNum >= fNumRows) { velocity.u = 0.0; velocity.v = 0.0; return velocity; } return INDEXH(fGridHdl, rowNum * fNumCols + colNum); }
void ExchangeSegs(SEGMENTH S, long a, long b) { long i; Segment m; // old way //m = INDEXH(S, a); //INDEXH(S, a) = INDEXH(S, b); //INDEXH(S, b) = m; // new way m = INDEXH(S, b); for (i = b ; i > a ; i--) INDEXH(S, i) = INDEXH(S, i - 1); INDEXH(S, a) = m; }
OSErr NetCDFWindMoverCurv::Read(BFPB *bfpb) { long i, version, index, numPoints; ClassID id; WorldPointF vertex; OSErr err = 0; if (err = NetCDFWindMover::Read(bfpb)) return err; StartReadWriteSequence("NetCDFWindMoverCurv::Read()"); if (err = ReadMacValue(bfpb,&id)) return err; if (id != GetClassID ()) { TechError("NetCDFWindMoverCurv::Read()", "id != TYPE_NETCDFWINDMOVERCURV", 0); return -1; } if (err = ReadMacValue(bfpb,&version)) return err; if (version != NetCDFWindMoverCurvREADWRITEVERSION) { printSaveFileVersionError(); return -1; } //// if (err = ReadMacValue(bfpb, &numPoints)) goto done; if (numPoints > 0) { fVerdatToNetCDFH = (LONGH)_NewHandleClear(sizeof(long)*numPoints); // for curvilinear if(!fVerdatToNetCDFH) {TechError("NetCDFWindMoverCurv::Read()", "_NewHandle()", 0); err = memFullErr; goto done;} for (i = 0 ; i < numPoints ; i++) { if (err = ReadMacValue(bfpb, &index)) goto done; INDEXH(fVerdatToNetCDFH, i) = index; } } if (err = ReadMacValue(bfpb, &numPoints)) goto done; fVertexPtsH = (WORLDPOINTFH)_NewHandleClear(sizeof(WorldPointF)*numPoints); // for curvilinear if(!fVertexPtsH) {TechError("NetCDFWindMoverCurv::Read()", "_NewHandle()", 0); err = memFullErr; goto done;} for (i = 0 ; i < numPoints ; i++) { if (err = ReadMacValue(bfpb, &vertex.pLat)) goto done; if (err = ReadMacValue(bfpb, &vertex.pLong)) goto done; INDEXH(fVertexPtsH, i) = vertex; } done: if(err) { TechError("NetCDFWindMoverCurv::Read(char* path)", " ", 0); if(fVerdatToNetCDFH) {DisposeHandle((Handle)fVerdatToNetCDFH); fVerdatToNetCDFH=0;} if(fVertexPtsH) {DisposeHandle((Handle)fVertexPtsH); fVertexPtsH=0;} } return err; }
OSErr AddSegment(SEGMENTH *segments, long *numSegs, Segment s) { _SetHandleSize((Handle)*segments, ((*numSegs) + 1) * sizeof(Segment)); if (_MemError()) { TechError("AddSegment()", "_SetHandleSize()", 0); return -1; } INDEXH(*segments, *numSegs) = s; (*numSegs)++; return 0; }
OSErr ComponentMover_c::GetAveragedWindValue(Seconds time, const Seconds& time_step, VelocityRec *avValue) { long index, numValuesInHdl; VelocityRec avWindValue = {0.,0.}; Seconds avTime, elapsed_time; *avValue = avWindValue; elapsed_time = time - fModelStartTime; index = (elapsed_time) / time_step; //index = (long)((time - fModelStartTime)/time_step); numValuesInHdl = _GetHandleSize((Handle)fAveragedWindsHdl)/sizeof(**fAveragedWindsHdl); if (index<0 || index >= numValuesInHdl) {return -1;} // may want to recalculate avTime = INDEXH(fAveragedWindsHdl, index).time; if (avTime != time) return -1; *avValue = INDEXH(fAveragedWindsHdl, index).value;// translate back to u,v return noErr; }
WorldRect LEList_c::GetLEBounds() { long i; WorldPoint p; WorldRect bounds = voidWorldRect; for (i = 0 ; i < this->numOfLEs ; i++) { p = INDEXH(LEHandle, i).p; AddWPointToWRect(p.pLat, p.pLong, &bounds); } return bounds; }
OSErr TimeGridWindCurv::Write (BFPB *bfpb) { long i, version = TimeGridWindCurvREADWRITEVERSION; //JLM ClassID id = GetClassID (); long numPoints, index; WorldPointF vertex; OSErr err = 0; if (err = TimeGridWindRect::Write (bfpb)) return err; StartReadWriteSequence("TimeGridWindCurv::Write()"); if (err = WriteMacValue(bfpb, id)) return err; if (err = WriteMacValue(bfpb, version)) return err; //// numPoints = _GetHandleSize((Handle)fVerdatToNetCDFH)/sizeof(**fVerdatToNetCDFH); if (err = WriteMacValue(bfpb, numPoints)) goto done; for (i=0;i<numPoints;i++) { index = INDEXH(fVerdatToNetCDFH,i); if (err = WriteMacValue(bfpb, index)) goto done; } numPoints = _GetHandleSize((Handle)fVertexPtsH)/sizeof(**fVertexPtsH); if (err = WriteMacValue(bfpb, numPoints)) goto done; for (i=0;i<numPoints;i++) { vertex = INDEXH(fVertexPtsH,i); if (err = WriteMacValue(bfpb, vertex.pLat)) goto done; if (err = WriteMacValue(bfpb, vertex.pLong)) goto done; } done: if(err) TechError("TimeGridWindCurv::Write(char* path)", " ", 0); return err; }
//Boolean NetCDFMoverCurv_c::ThereIsAdjacentLand2(LONGH maskH, VelocityFH velocityH, long numRows, long numCols, long row, long col) Boolean ThereIsAdjacentLand2(LONGH maskH, DOUBLEH landmaskH, long numRows, long numCols, long row, long col) { long i, j, iStart, iEnd, jStart, jEnd, lowestLandIndex = 0; long neighbor; iStart = (row > 0) ? row - 1 : 0; jStart = (col > 0) ? col - 1 : 0; iEnd = (row < numRows - 1) ? row + 1 : numRows - 1; jEnd = (col < numCols - 1) ? col + 1 : numCols - 1; /*for (i = iStart; i < iEnd+1; i++) { for (j = jStart; j < jEnd+1; j++) { if (i==row && j==col) continue; neighbor = INDEXH(maskH, i*fNumCols + j); // eventually should use a land mask or fill value to identify land if (neighbor >= 3 || (INDEXH(velocityH,i*fNumCols+j).u==0. && INDEXH(velocityH,i*fNumCols+j).v==0.)) return true; } }*/ for (i = iStart; i < iEnd+1; i++) { if (i==row) continue; neighbor = INDEXH(maskH, i*numCols + col); //if (neighbor >= 3 || (INDEXH(velocityH,i*fNumCols+j).u==fFillValue && INDEXH(velocityH,i*fNumCols+j).v==fFillValue)) return true; //if (neighbor >= 3 || (INDEXH(velocityH,i*numCols+col).u==fFillValue && INDEXH(velocityH,i*numCols+col).v==fFillValue)) return true; if (neighbor >= 3 || INDEXH(landmaskH,i*numCols+col)==0) return true; } for (j = jStart; j< jEnd+1; j++) { if (j==col) continue; neighbor = INDEXH(maskH, row*numCols + j); //if (neighbor >= 3 || (INDEXH(velocityH,i*fNumCols+j).u==fFillValue && INDEXH(velocityH,i*fNumCols+j).v==fFillValue)) return true; //if (neighbor >= 3 || (INDEXH(velocityH,row*numCols+j).u==fFillValue && INDEXH(velocityH,row*numCols+j).v==fFillValue)) return true; if (neighbor >= 3 || INDEXH(landmaskH,row*numCols+j)==0) return true; } return false; }
long CheckSurroundingPoints(LONGH maskH, long numRows, long numCols, long row, long col) { long i, j, iStart, iEnd, jStart, jEnd, lowestLandIndex = 0; long neighbor; iStart = (row > 0) ? row - 1 : 0; jStart = (col > 0) ? col - 1 : 0; iEnd = (row < numRows - 1) ? row + 1 : numRows - 1; jEnd = (col < numCols - 1) ? col + 1 : numCols - 1; // don't allow diagonals for now,they could be separate small islands /*for (i = iStart; i< iEnd+1; i++) { for (j = jStart; j< jEnd+1; j++) { if (i==row && j==col) continue; neighbor = INDEXH(maskH, i*fNumCols + j); if (neighbor >= 3 && neighbor < lowestLandIndex) lowestLandIndex = neighbor; } }*/ for (i = iStart; i< iEnd+1; i++) { if (i==row) continue; neighbor = INDEXH(maskH, i*numCols + col); if (neighbor >= 3 && neighbor < lowestLandIndex) lowestLandIndex = neighbor; } for (j = jStart; j< jEnd+1; j++) { if (j==col) continue; neighbor = INDEXH(maskH, row*numCols + j); if (neighbor >= 3 && neighbor < lowestLandIndex) lowestLandIndex = neighbor; } return lowestLandIndex; }
VelocityRec RectGridVel_c::GetSmoothVelocity(WorldPoint p) { long rowNum, colNum; VelocityRec velocity, velNew; LongRect gridLRect, geoRect; ScaleRec thisScaleRec; SetLRect(&gridLRect, 0, fNumRows, fNumCols, 0); SetLRect(&geoRect, fGridBounds.loLong, fGridBounds.loLat, fGridBounds.hiLong, fGridBounds.hiLat); GetLScaleAndOffsets(&geoRect, &gridLRect, &thisScaleRec); colNum = (long)(p.pLong * thisScaleRec.XScale + thisScaleRec.XOffset); rowNum = (long)(p.pLat * thisScaleRec.YScale + thisScaleRec.YOffset); velocity = GetPatValue(p); if (colNum > 0 && colNum < fNumCols - 1 && rowNum > 0 && rowNum < fNumRows - 1) { VelocityRec topV, leftV, bottomV, rightV; topV = INDEXH (fGridHdl, rowNum + 1 * fNumCols + colNum); bottomV = INDEXH (fGridHdl, rowNum - 1 * fNumCols + colNum); leftV = INDEXH (fGridHdl, rowNum * fNumCols + colNum - 1); rightV = INDEXH (fGridHdl, rowNum * fNumCols + colNum + 1); velNew.u = .5 * velocity.u + .125 * (topV.u + bottomV.u + leftV.u + rightV.u); velNew.v = .5 * velocity.v + .125 * (topV.v + bottomV.v + leftV.v + rightV.v); } else velNew = velocity; return velNew; }
float TriCurMover_c::GetMaxDepth(void) { long i,numDepths; float depth, maxDepth = -9999.0; if (!fDepthDataInfo) return 0; // some error alert, no depth info to check numDepths = _GetHandleSize((Handle)fDepthDataInfo)/sizeof(**fDepthDataInfo); for (i=0;i<numDepths;i++) { depth = INDEXH(fDepthDataInfo,i).totalDepth; // depth at triangle if (depth > maxDepth) maxDepth = depth; } return maxDepth; }
void LEList_c::GetLEStatistics(long* numReleased,long* numEvaporated,long* numBeached, long* numOffMap, long* numFloating) { long i,numNotReleased = 0; *numEvaporated = *numBeached = *numOffMap = *numFloating = 0; if (LEHandle) { for (i = 0 ; i < this->numOfLEs ; i++) { switch( INDEXH(LEHandle, i).statusCode) { case OILSTAT_NOTRELEASED: numNotReleased++; break; case OILSTAT_OFFMAPS: (*numOffMap)++; break; case OILSTAT_ONLAND: (*numBeached)++; break; case OILSTAT_EVAPORATED: (*numEvaporated)++; break; case OILSTAT_INWATER:(*numFloating)++; break; } } } *numReleased = this->numOfLEs - numNotReleased; }
float Map3D_c::GetMaxDepth2(void) { // may want to extend for SIGMA_ROMS (all ROMS?) to check the cell depths rather than point depths long i,numDepths; float depth, maxDepth=0; FLOATH depthsHdl = 0; TTriGridVel* triGrid = GetGrid(); // don't use refined grid, depths aren't refined if (!triGrid) return 0; // some error alert, no depth info to check depthsHdl = triGrid->GetBathymetry(); if (!depthsHdl) return 0; // some error alert, no depth info to check numDepths = _GetHandleSize((Handle)depthsHdl)/sizeof(**depthsHdl); for (i=0;i<numDepths;i++) { depth = INDEXH(depthsHdl,i); if (depth > maxDepth) maxDepth = depth; } return maxDepth; }
Boolean InteriorLandPoint(LONGH maskH, long numRows, long numCols, long row, long col) { long i, j, iStart, iEnd, jStart, jEnd; long neighbor; long numRows_ext = numRows+1, numCols_ext = numCols+1; iStart = (row > 0) ? row - 1 : 0; jStart = (col > 0) ? col - 1 : 0; iEnd = (row < numRows_ext - 1) ? row + 1 : numRows_ext - 1; jEnd = (col < numCols_ext - 1) ? col + 1 : numCols_ext - 1; /*for (i = iStart; i < iEnd+1; i++) { if (i==row) continue; neighbor = INDEXH(maskH, i*fNumCols_ext + col); if (neighbor < 3) // water point return false; } for (j = jStart; j< jEnd+1; j++) { if (j==col) continue; neighbor = INDEXH(maskH, row*fNumCols_ext + j); if (neighbor < 3) // water point return false; }*/ //for (i = iStart; i < iEnd+1; i++) // point is in lower left corner of grid box (land), so only check 3 other quadrants of surrounding 'square' for (i = row; i < iEnd+1; i++) { //for (j = jStart; j< jEnd+1; j++) for (j = jStart; j< jEnd; j++) { if (i==row && j==col) continue; neighbor = INDEXH(maskH, i*numCols_ext + j); if (neighbor < 3 /*&& neighbor != -1*/) // water point return false; //if (row==1 && INDEXH(maskH,j)==1) return false; } } return true; }
void SortSegments(SEGMENTH S, long numSegs) { long i, startPiece, nextPos = 0; while (nextPos < numSegs) { // find a segment whose FROM doesn't match the FROM or TO of any other segment for (startPiece = nextPos ; startPiece < numSegs ; startPiece++) { // check next and previous first as a special case if (startPiece > 0) if ( (INDEXH(S, startPiece).fromLat == INDEXH(S, startPiece - 1).fromLat && INDEXH(S, startPiece).fromLong == INDEXH(S, startPiece - 1).fromLong) || (INDEXH(S, startPiece).fromLat == INDEXH(S, startPiece - 1).toLat && INDEXH(S, startPiece).fromLong == INDEXH(S, startPiece - 1).toLong) ) continue; if (startPiece < (numSegs - 1)) if ( (INDEXH(S, startPiece).fromLat == INDEXH(S, startPiece + 1).fromLat && INDEXH(S, startPiece).fromLong == INDEXH(S, startPiece + 1).fromLong) || (INDEXH(S, startPiece).fromLat == INDEXH(S, startPiece + 1).toLat && INDEXH(S, startPiece).fromLong == INDEXH(S, startPiece + 1).toLong) ) continue; // check all segments for (i = nextPos ; i < numSegs ; i++) { if (i == startPiece) continue; if ( (INDEXH(S, startPiece).fromLat == INDEXH(S, i).fromLat && INDEXH(S, startPiece).fromLong == INDEXH(S, i).fromLong) || (INDEXH(S, startPiece).fromLat == INDEXH(S, i).toLat && INDEXH(S, startPiece).fromLong == INDEXH(S, i).toLong) ) break; } if (i == numSegs) break; } if (startPiece == numSegs) { // couldn't find one, // so try to find a segment whose TO doesn't match the FROM or TO of any other segment for (startPiece = nextPos ; startPiece < numSegs ; startPiece++) { // check next and previous first as a special case if (startPiece > 0) if ( (INDEXH(S, startPiece).toLat == INDEXH(S, startPiece - 1).fromLat && INDEXH(S, startPiece).toLong == INDEXH(S, startPiece - 1).fromLong) || (INDEXH(S, startPiece).toLat == INDEXH(S, startPiece - 1).toLat && INDEXH(S, startPiece).fromLong == INDEXH(S, startPiece - 1).toLong) ) continue; if (startPiece < (numSegs - 1)) if ( (INDEXH(S, startPiece).toLat == INDEXH(S, startPiece + 1).fromLat && INDEXH(S, startPiece).toLong == INDEXH(S, startPiece + 1).fromLong) || (INDEXH(S, startPiece).toLat == INDEXH(S, startPiece + 1).toLat && INDEXH(S, startPiece).toLong == INDEXH(S, startPiece + 1).toLong) ) continue; for (i = nextPos ; i < numSegs ; i++) { if (i == startPiece) continue; if ( (INDEXH(S, startPiece).toLat == INDEXH(S, i).fromLat && INDEXH(S, startPiece).toLong == INDEXH(S, i).fromLong) || (INDEXH(S, startPiece).toLat == INDEXH(S, i).toLat && INDEXH(S, startPiece).toLong == INDEXH(S, i).toLong) ) break; } if (i == numSegs) { // reverse the segment, since we want to follow its TO chain SwitchLongs(&INDEXH(S, startPiece).toLat, &INDEXH(S, startPiece).fromLat); SwitchLongs(&INDEXH(S, startPiece).toLong, &INDEXH(S, startPiece).fromLong); break; } } if (startPiece == numSegs) // at this point we've checked all the remaining segments and all of their // FROM and TO points are inter-connected, // so we have a ring and can choose the first segment arbitrarily as the start startPiece = nextPos; } // string the TO chain starting from it until a segment without a TO is reached if (startPiece != nextPos) ExchangeSegs(S, nextPos, startPiece); nextPos++; while (nextPos < numSegs) { for (i = nextPos ; i < numSegs ; i++) { if ( (INDEXH(S, i).fromLat == INDEXH(S, nextPos - 1).toLat && INDEXH(S, i).fromLong == INDEXH(S, nextPos - 1).toLong) || (INDEXH(S, i).toLat == INDEXH(S, nextPos - 1).toLat && INDEXH(S, i).toLong == INDEXH(S, nextPos - 1).toLong) ) break; } if (i == numSegs) break; if (i != nextPos) ExchangeSegs(S, nextPos, i); if (INDEXH(S, nextPos).toLat == INDEXH(S, nextPos - 1).toLat && INDEXH(S, nextPos).toLong == INDEXH(S, nextPos - 1).toLong) { // reverse SwitchLongs(&INDEXH(S, nextPos).toLat, &INDEXH(S, nextPos).fromLat); SwitchLongs(&INDEXH(S, nextPos).toLong, &INDEXH(S, nextPos).fromLong); } nextPos++; } } }
void TimeGridWindCurv::Draw(Rect r, WorldRect view, double refScale, double arrowScale,double arrowDepth, Boolean bDrawArrows, Boolean bDrawGrid, RGBColor arrowColor) { // use for curvilinear WorldPoint wayOffMapPt = {-200*1000000,-200*1000000}; double timeAlpha; Point p; Rect c; Seconds startTime,endTime; Seconds time = model->GetModelTime(); OSErr err = 0; char errmsg[256]; RGBForeColor(&arrowColor); if(bDrawArrows || bDrawGrid) { if (bDrawGrid) // make sure to draw grid even if don't draw arrows { ((TTriGridVel*)fGrid)->DrawCurvGridPts(r,view); //return; } if (bDrawArrows) { // we have to draw the arrows long numVertices,i; LongPointHdl ptsHdl = 0; long timeDataInterval; Boolean loaded; TTriGridVel* triGrid = (TTriGridVel*)fGrid; err = this -> SetInterval(errmsg, model->GetModelTime()); // AH 07/17/2012 if(err) return; loaded = this -> CheckInterval(timeDataInterval, model->GetModelTime()); // AH 07/17/2012 if(!loaded) return; ptsHdl = triGrid -> GetPointsHdl(); if(ptsHdl) numVertices = _GetHandleSize((Handle)ptsHdl)/sizeof(**ptsHdl); else numVertices = 0; // Check for time varying wind if( (GetNumTimesInFile()>1 || GetNumFiles()>1 )&& loaded && !err) { // Calculate the time weight factor startTime = (*fTimeHdl)[fStartData.timeIndex] + fTimeShift; //endTime = (*fTimeHdl)[fEndData.timeIndex] + fTimeShift; //timeAlpha = (endTime - time)/(double)(endTime - startTime); if (fEndData.timeIndex == UNASSIGNEDINDEX && (time > startTime || time < startTime) && fAllowExtrapolationInTime) { timeAlpha = 1; } else { //return false; endTime = (*fTimeHdl)[fEndData.timeIndex] + fTimeShift; timeAlpha = (endTime - time)/(double)(endTime - startTime); } } for(i = 0; i < numVertices; i++) { // get the value at each vertex and draw an arrow LongPoint pt = INDEXH(ptsHdl,i); long ptIndex=-1,iIndex,jIndex; WorldPoint wp,wp2; Point p,p2; VelocityRec velocity = {0.,0.}; Boolean offQuickDrawPlane = false; wp.pLat = pt.v; wp.pLong = pt.h; ptIndex = INDEXH(fVerdatToNetCDFH,i); iIndex = ptIndex/(fNumCols+1); jIndex = ptIndex%(fNumCols+1); if (iIndex>0 && jIndex<fNumCols) ptIndex = (iIndex-1)*(fNumCols)+jIndex; else ptIndex = -1; // for now draw arrow at midpoint of diagonal of gridbox // this will result in drawing some arrows more than once if (GetLatLonFromIndex(iIndex-1,jIndex+1,&wp2)!=-1) // may want to get all four points and interpolate { wp.pLat = (wp.pLat + wp2.pLat)/2.; wp.pLong = (wp.pLong + wp2.pLong)/2.; } p = GetQuickDrawPt(wp.pLong, wp.pLat, &r, &offQuickDrawPlane); // should put velocities in center of grid box // Should check vs fFillValue // Check for constant wind if( (( GetNumTimesInFile()==1 &&!(GetNumFiles()>1) ) || timeAlpha == 1) && ptIndex!=-1) { velocity.u = INDEXH(fStartData.dataHdl,ptIndex).u; velocity.v = INDEXH(fStartData.dataHdl,ptIndex).v; } else if (ptIndex!=-1)// time varying wind { // need to rescale velocities for Navy case, store angle velocity.u = timeAlpha*INDEXH(fStartData.dataHdl,ptIndex).u + (1-timeAlpha)*INDEXH(fEndData.dataHdl,ptIndex).u; velocity.v = timeAlpha*INDEXH(fStartData.dataHdl,ptIndex).v + (1-timeAlpha)*INDEXH(fEndData.dataHdl,ptIndex).v; } if ((velocity.u != 0 || velocity.v != 0) && (velocity.u != fFillValue && velocity.v != fFillValue)) { float inchesX = (velocity.u * refScale) / arrowScale; float inchesY = (velocity.v * refScale) / arrowScale; short pixX = inchesX * PixelsPerInchCurrent(); short pixY = inchesY * PixelsPerInchCurrent(); p2.h = p.h + pixX; p2.v = p.v - pixY; MyMoveTo(p.h, p.v); MyLineTo(p2.h, p2.v); MyDrawArrow(p.h,p.v,p2.h,p2.v); } } } } if (bDrawGrid) fGrid->Draw(r,view,wayOffMapPt,refScale,arrowScale,0.,false,true,arrowColor); RGBForeColor(&colors[BLACK]); }
Boolean TimeGridWindCurv::VelocityStrAtPoint(WorldPoint3D wp, char *diagnosticStr, double arrowDepth) { char uStr[32],sStr[32],errmsg[64]; double lengthU, lengthS; VelocityRec velocity = {0.,0.}; OSErr err = 0; Seconds startTime, endTime, time = model->GetModelTime(); double timeAlpha; long index; LongPoint indices; long ptIndex1,ptIndex2,ptIndex3; InterpolationVal interpolationVal; if (fGrid) { // for now just use the u,v at left and bottom midpoints of grid box as velocity over entire gridbox index = ((TTriGridVel*)fGrid)->GetRectIndexFromTriIndex(wp.p,fVerdatToNetCDFH,fNumCols+1);// curvilinear grid if (index < 0) return 0; indices = this->GetVelocityIndices(wp.p); } // Check for constant current if((GetNumTimesInFile()==1 /*&& !(GetNumFiles()>1)*/) || (fEndData.timeIndex == UNASSIGNEDINDEX && time > ((*fTimeHdl)[fStartData.timeIndex] + fTimeShift) && fAllowExtrapolationInTime) || (fEndData.timeIndex == UNASSIGNEDINDEX && time < ((*fTimeHdl)[fStartData.timeIndex] + fTimeShift) && fAllowExtrapolationInTime)) //if(GetNumTimesInFile()==1) { // Calculate the interpolated velocity at the point if (index >= 0) { velocity.u = INDEXH(fStartData.dataHdl,index).u; velocity.v = INDEXH(fStartData.dataHdl,index).v; } else // set vel to zero { velocity.u = 0.; velocity.v = 0.; } } else // time varying current { // Calculate the time weight factor // Calculate the time weight factor startTime = (*fTimeHdl)[fStartData.timeIndex] + fTimeShift; endTime = (*fTimeHdl)[fEndData.timeIndex] + fTimeShift; timeAlpha = (endTime - time)/(double)(endTime - startTime); // Calculate the interpolated velocity at the point if (index >= 0) { velocity.u = timeAlpha*INDEXH(fStartData.dataHdl,index).u + (1-timeAlpha)*INDEXH(fEndData.dataHdl,index).u; velocity.v = timeAlpha*INDEXH(fStartData.dataHdl,index).v + (1-timeAlpha)*INDEXH(fEndData.dataHdl,index).v; } else // set vel to zero { velocity.u = 0.; velocity.v = 0.; } } lengthU = sqrt(velocity.u * velocity.u + velocity.v * velocity.v); //lengthS = this->fWindScale * lengthU; // pass this in if there is a dialog scale factor lengthS = lengthU * fVar.fileScaleFactor; StringWithoutTrailingZeros(uStr,lengthU,4); StringWithoutTrailingZeros(sStr,lengthS,4); if (indices.h >= 0 && fNumRows-indices.v-1 >=0 && indices.h < fNumCols && fNumRows-indices.v-1 < fNumRows) { sprintf(diagnosticStr, " [grid: %s, unscaled: %s m/s, scaled: %s m/s], file indices : [%ld, %ld]", fVar.userName, uStr, sStr, fNumRows-indices.v-1, indices.h); //sprintf(diagnosticStr, " [unscaled: %s m/s, scaled: %s m/s], file indices : [%ld, %ld]", //uStr, sStr, fNumRows-indices.v-1, indices.h); } else { sprintf(diagnosticStr, " [grid: %s, unscaled: %s m/s, scaled: %s m/s]", fVar.userName, uStr, sStr); //sprintf(diagnosticStr, " [unscaled: %s m/s, scaled: %s m/s]", //uStr, sStr); } return true; }
void TimeGridWindRect::Draw(Rect r, WorldRect view, double refScale, double arrowScale,double arrowDepth, Boolean bDrawArrows, Boolean bDrawGrid, RGBColor arrowColor) { // Use this for regular grid short row, col, pixX, pixY; long dLong, dLat, index, timeDataInterval; float inchesX, inchesY; double timeAlpha; Seconds startTime, endTime, time = model->GetModelTime(); Point p, p2; WorldPoint wp; WorldRect boundsRect, bounds; VelocityRec velocity; Rect c, newGridRect = {0, 0, fNumRows - 1, fNumCols - 1}; // fNumRows, fNumCols members of TimeGridVel Boolean offQuickDrawPlane = false, loaded; char errmsg[256]; OSErr err = 0; TRectGridVel* rectGrid = (TRectGridVel*)fGrid; if (!bDrawArrows && !bDrawGrid) return; bounds = rectGrid->GetBounds(); // need to get the bounds from the grid dLong = (WRectWidth(bounds) / fNumCols) / 2; dLat = (WRectHeight(bounds) / fNumRows) / 2; //RGBForeColor(&colors[PURPLE]); RGBForeColor(&arrowColor); boundsRect = bounds; InsetWRect (&boundsRect, dLong, dLat); if (bDrawArrows) { err = this -> SetInterval(errmsg, model->GetModelTime()); // AH 07/17/2012 if(err && !bDrawGrid) return; // want to show grid even if there's no wind data loaded = this -> CheckInterval(timeDataInterval, model->GetModelTime()); if(!loaded && !bDrawGrid) return; if((GetNumTimesInFile()>1 || GetNumFiles()>1) && loaded && !err) { // Calculate the time weight factor if (GetNumFiles()>1 && fOverLap) startTime = fOverLapStartTime + fTimeShift; else startTime = (*fTimeHdl)[fStartData.timeIndex] + fTimeShift; if (fEndData.timeIndex == UNASSIGNEDINDEX && (time > startTime || time < startTime) && fAllowExtrapolationInTime) { timeAlpha = 1; } else { //return false; endTime = (*fTimeHdl)[fEndData.timeIndex] + fTimeShift; timeAlpha = (endTime - time)/(double)(endTime - startTime); } } } for (row = 0 ; row < fNumRows ; row++) for (col = 0 ; col < fNumCols ; col++) { SetPt(&p, col, row); wp = ScreenToWorldPoint(p, newGridRect, boundsRect); velocity.u = velocity.v = 0.; if (loaded && !err) { index = dynamic_cast<TimeGridWindRect *>(this)->GetVelocityIndex(wp); if (bDrawArrows && index >= 0) { // Check for constant wind pattern if((GetNumTimesInFile()==1 && !(GetNumFiles()>1)) || timeAlpha==1) { velocity.u = INDEXH(fStartData.dataHdl,index).u; velocity.v = INDEXH(fStartData.dataHdl,index).v; } else // time varying wind { velocity.u = timeAlpha*INDEXH(fStartData.dataHdl,index).u + (1-timeAlpha)*INDEXH(fEndData.dataHdl,index).u; velocity.v = timeAlpha*INDEXH(fStartData.dataHdl,index).v + (1-timeAlpha)*INDEXH(fEndData.dataHdl,index).v; } } } p = GetQuickDrawPt(wp.pLong, wp.pLat, &r, &offQuickDrawPlane); MySetRect(&c, p.h - 1, p.v - 1, p.h + 1, p.v + 1); if (bDrawGrid && bDrawArrows && (velocity.u != 0 || velocity.v != 0)) PaintRect(&c); // should check fill_value if (bDrawGrid && !bDrawArrows) PaintRect(&c); // should check fill_value if (bDrawArrows && (velocity.u != 0 || velocity.v != 0)) { inchesX = (velocity.u * refScale) / arrowScale; inchesY = (velocity.v * refScale) / arrowScale; pixX = inchesX * PixelsPerInchCurrent(); pixY = inchesY * PixelsPerInchCurrent(); p2.h = p.h + pixX; p2.v = p.v - pixY; MyMoveTo(p.h, p.v); MyLineTo(p2.h, p2.v); MyDrawArrow(p.h,p.v,p2.h,p2.v); } } RGBForeColor(&colors[BLACK]); }
WorldPoint3D GridWndMover_c::GetMove(const Seconds& model_time, Seconds timeStep,long setIndex,long leIndex,LERec *theLE,LETYPE leType) { double dLong, dLat; WorldPoint3D deltaPoint ={0,0,0.}; WorldPoint refPoint = (*theLE).p; double timeAlpha; long index; Seconds startTime,endTime; Seconds time = model->GetModelTime(); VelocityRec windVelocity; OSErr err = noErr; char errmsg[256]; // if ((*theLE).z > 0) return deltaPoint; // wind doesn't act below surface // or use some sort of exponential decay below the surface... if(!fIsOptimizedForStep) { err = dynamic_cast<GridWndMover *>(this) -> SetInterval(errmsg, model_time); // AH 07/17/2012 if (err) return deltaPoint; } index = GetVelocityIndex(refPoint); // regular grid // Check for constant wind if(dynamic_cast<GridWndMover *>(this)->GetNumTimesInFile()==1) { // Calculate the interpolated velocity at the point if (index >= 0) { windVelocity.u = INDEXH(fStartData.dataHdl,index).u; windVelocity.v = INDEXH(fStartData.dataHdl,index).v; } else // set vel to zero { windVelocity.u = 0.; windVelocity.v = 0.; } } else // time varying wind { // Calculate the time weight factor if (dynamic_cast<GridWndMover *>(this)->GetNumFiles()>1 && fOverLap) startTime = fOverLapStartTime; else startTime = (*fTimeDataHdl)[fStartData.timeIndex].time; //startTime = (*fTimeDataHdl)[fStartData.timeIndex].time; endTime = (*fTimeDataHdl)[fEndData.timeIndex].time; timeAlpha = (endTime - time)/(double)(endTime - startTime); // Calculate the interpolated velocity at the point if (index >= 0) { windVelocity.u = timeAlpha*INDEXH(fStartData.dataHdl,index).u + (1-timeAlpha)*INDEXH(fEndData.dataHdl,index).u; windVelocity.v = timeAlpha*INDEXH(fStartData.dataHdl,index).v + (1-timeAlpha)*INDEXH(fEndData.dataHdl,index).v; } else // set vel to zero { windVelocity.u = 0.; windVelocity.v = 0.; } } //scale: windVelocity.u *= fWindScale; windVelocity.v *= fWindScale; if(leType == UNCERTAINTY_LE) { err = AddUncertainty(setIndex,leIndex,&windVelocity); } windVelocity.u *= (*theLE).windage; windVelocity.v *= (*theLE).windage; dLong = ((windVelocity.u / METERSPERDEGREELAT) * timeStep) / LongToLatRatio3 (refPoint.pLat); dLat = (windVelocity.v / METERSPERDEGREELAT) * timeStep; deltaPoint.p.pLong = dLong * 1000000; deltaPoint.p.pLat = dLat * 1000000; return deltaPoint; }
//OSErr NetCDFWindMoverCurv::ReadTopology(char* path, TMap **newMap) OSErr NetCDFWindMoverCurv::ReadTopology(vector<string> &linesInFile, TMap **newMap) { // import NetCDF curvilinear info so don't have to regenerate char s[1024], errmsg[256]/*, s[256], topPath[256]*/; long i, numPoints, numTopoPoints, line = 0, numPts; string currentLine; //CHARH f = 0; OSErr err = 0; TopologyHdl topo=0; LongPointHdl pts=0; FLOATH depths=0; VelocityFH velH = 0; DAGTreeStruct tree; WorldRect bounds = voidWorldRect; TTriGridVel *triGrid = nil; tree.treeHdl = 0; TDagTree *dagTree = 0; long numWaterBoundaries, numBoundaryPts, numBoundarySegs; LONGH boundarySegs=0, waterBoundaries=0, boundaryPts=0; errmsg[0]=0; /*if (!path || !path[0]) return 0; if (err = ReadFileContents(TERMINATED,0, 0, path, 0, 0, &f)) { TechError("NetCDFWindMover::ReadTopology()", "ReadFileContents()", err); goto done; } _HLock((Handle)f); // JLM 8/4/99 */ // No header // start with transformation array and vertices MySpinCursor(); // JLM 8/4/99 //NthLineInTextOptimized(*f, (line)++, s, 1024); currentLine = linesInFile[line++]; //if(IsTransposeArrayHeaderLine(s,&numPts)) // if(IsTransposeArrayHeaderLine(currentLine,numPts)) // { //if (err = ReadTransposeArray(f,&line,&fVerdatToNetCDFH,numPts,errmsg)) if (err = ReadTransposeArray(linesInFile,&line,&fVerdatToNetCDFH,numPts,errmsg)) {strcpy(errmsg,"Error in ReadTransposeArray"); goto done;} } else {err=-1; strcpy(errmsg,"Error in Transpose header line"); goto done;} //if(err = ReadTVertices(f,&line,&pts,&depths,errmsg)) goto done; if(err = ReadTVertices(linesInFile,&line,&pts,&depths,errmsg)) goto done; if(pts) { LongPoint thisLPoint; numPts = _GetHandleSize((Handle)pts)/sizeof(LongPoint); if(numPts > 0) { WorldPoint wp; for(i=0;i<numPts;i++) { thisLPoint = INDEXH(pts,i); wp.pLat = thisLPoint.v; wp.pLong = thisLPoint.h; AddWPointToWRect(wp.pLat, wp.pLong, &bounds); } } } MySpinCursor(); currentLine = linesInFile[line++]; //NthLineInTextOptimized(*f, (line)++, s, 1024); //code goes here, boundary points //if(IsBoundarySegmentHeaderLine(s,&numBoundarySegs)) // Boundary data from CATs if(IsBoundarySegmentHeaderLine(currentLine,numBoundarySegs)) // Boundary data from CATs { MySpinCursor(); if (numBoundarySegs>0) //err = ReadBoundarySegs(f,&line,&boundarySegs,numBoundarySegs,errmsg); err = ReadBoundarySegs(linesInFile,&line,&boundarySegs,numBoundarySegs,errmsg); if(err) goto done; //NthLineInTextOptimized(*f, (line)++, s, 1024); currentLine = linesInFile[line++]; } else { //err = -1; //strcpy(errmsg,"Error in Boundary segment header line"); //goto done; // not needed for 2D files, but we require for now } MySpinCursor(); // JLM 8/4/99 //if(IsWaterBoundaryHeaderLine(s,&numWaterBoundaries,&numBoundaryPts)) // Boundary types from CATs if(IsWaterBoundaryHeaderLine(currentLine,numWaterBoundaries,numBoundaryPts)) // Boundary types from CATs { MySpinCursor(); if (numBoundaryPts>0) //err = ReadWaterBoundaries(f,&line,&waterBoundaries,numWaterBoundaries,numBoundaryPts,errmsg); err = ReadWaterBoundaries(linesInFile,&line,&waterBoundaries,numWaterBoundaries,numBoundaryPts,errmsg); if(err) goto done; //NthLineInTextOptimized(*f, (line)++, s, 1024); currentLine = linesInFile[line++]; } else { //err = -1; //strcpy(errmsg,"Error in Water boundaries header line"); //goto done; // not needed for 2D files, but we require for now } MySpinCursor(); // JLM 8/4/99 //NthLineInTextOptimized(*f, (line)++, s, 1024); //if(IsBoundaryPointsHeaderLine(s,&numBoundaryPts)) // Boundary data from CATs if(IsBoundaryPointsHeaderLine(currentLine,numBoundaryPts)) // Boundary data from CATs { MySpinCursor(); if (numBoundaryPts>0) //err = ReadBoundaryPts(f,&line,&boundaryPts,numBoundaryPts,errmsg); err = ReadBoundaryPts(linesInFile,&line,&boundaryPts,numBoundaryPts,errmsg); if(err) goto done; //NthLineInTextOptimized(*f, (line)++, s, 1024); currentLine = linesInFile[line++]; } else { //err = -1; //strcpy(errmsg,"Error in Boundary segment header line"); //goto done; // not always needed ? probably always needed for curvilinear } MySpinCursor(); // JLM 8/4/99 //if(IsTTopologyHeaderLine(s,&numTopoPoints)) // Topology from CATs if(IsTTopologyHeaderLine(currentLine,numTopoPoints)) // Topology from CATs { MySpinCursor(); //err = ReadTTopologyBody(f,&line,&topo,&velH,errmsg,numTopoPoints,FALSE); err = ReadTTopologyBody(linesInFile,&line,&topo,&velH,errmsg,numTopoPoints,FALSE); if(err) goto done; //NthLineInTextOptimized(*f, (line)++, s, 1024); currentLine = linesInFile[line++]; } else { err = -1; // for now we require TTopology strcpy(errmsg,"Error in topology header line"); if(err) goto done; } MySpinCursor(); // JLM 8/4/99 //NthLineInTextOptimized(*f, (line)++, s, 1024); //if(IsTIndexedDagTreeHeaderLine(s,&numPoints)) // DagTree from CATs if(IsTIndexedDagTreeHeaderLine(currentLine,numPoints)) // DagTree from CATs { MySpinCursor(); //err = ReadTIndexedDagTreeBody(f,&line,&tree,errmsg,numPoints); err = ReadTIndexedDagTreeBody(linesInFile,&line,&tree,errmsg,numPoints); if(err) goto done; } else { err = -1; // for now we require TIndexedDagTree strcpy(errmsg,"Error in dag tree header line"); if(err) goto done; } MySpinCursor(); // JLM 8/4/99 ///////////////////////////////////////////////// // if the boundary information is in the file we'll need to create a bathymetry map (required for 3D) /*if (waterBoundaries && (this -> moverMap == model -> uMap)) { //PtCurMap *map = CreateAndInitPtCurMap(fVar.userName,bounds); // the map bounds are the same as the grid bounds PtCurMap *map = CreateAndInitPtCurMap("Extended Topology",bounds); // the map bounds are the same as the grid bounds if (!map) {strcpy(errmsg,"Error creating ptcur map"); goto done;} // maybe move up and have the map read in the boundary information map->SetBoundarySegs(boundarySegs); map->SetWaterBoundaries(waterBoundaries); *newMap = map; }*/ { // wind will always be on another map if (waterBoundaries) {DisposeHandle((Handle)waterBoundaries); waterBoundaries=0;} if (boundarySegs) {DisposeHandle((Handle)boundarySegs); boundarySegs=0;} if (boundaryPts) {DisposeHandle((Handle)boundaryPts); boundaryPts=0;} } /*if (!(this -> moverMap == model -> uMap)) // maybe assume rectangle grids will have map? { if (waterBoundaries) {DisposeHandle((Handle)waterBoundaries); waterBoundaries=0;} if (boundarySegs) {DisposeHandle((Handle)boundarySegs); boundarySegs=0;} }*/ ///////////////////////////////////////////////// triGrid = new TTriGridVel; if (!triGrid) { err = true; TechError("Error in NetCDFWindMover::ReadTopology()","new TTriGridVel" ,err); goto done; } fGrid = (TTriGridVel*)triGrid; triGrid -> SetBounds(bounds); //triGrid -> SetDepths(depths); dagTree = new TDagTree(pts,topo,tree.treeHdl,velH,tree.numBranches); if(!dagTree) { err = -1; printError("Unable to read Extended Topology file."); goto done; } triGrid -> SetDagTree(dagTree); pts = 0; // because fGrid is now responsible for it topo = 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 //depths = 0; done: if(depths) {DisposeHandle((Handle)depths); depths=0;} /*if(f) { _HUnlock((Handle)f); DisposeHandle((Handle)f); f = 0; }*/ if(err) { if(!errmsg[0]) strcpy(errmsg,"An error occurred in NetCDFWindMoverCurv::ReadTopology"); printError(errmsg); if(pts) {DisposeHandle((Handle)pts); pts=0;} if(topo) {DisposeHandle((Handle)topo); topo=0;} if(velH) {DisposeHandle((Handle)velH); velH=0;} if(depths) {DisposeHandle((Handle)depths); depths=0;} if(tree.treeHdl) {DisposeHandle((Handle)tree.treeHdl); tree.treeHdl=0;} if(fGrid) { fGrid ->Dispose(); delete fGrid; fGrid = 0; } if (*newMap) { (*newMap)->Dispose(); delete *newMap; *newMap=0; } if (waterBoundaries) {DisposeHandle((Handle)waterBoundaries); waterBoundaries=0;} if (boundarySegs) {DisposeHandle((Handle)boundarySegs); boundarySegs = 0;} if (boundaryPts) {DisposeHandle((Handle)boundaryPts); boundaryPts = 0;} } return err; }
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; }
SEGMENTH CombinePolygonPieces(SEGMENTH *A1, SEGMENTH *B1, Boolean keepAinB, Boolean keepAnotinB, Boolean keepBinA, Boolean keepBnotinA) { long i, j, err, numSegsA, numSegsB, numSegsC = 0; WorldPoint m; SEGMENTH C = 0, A2 = 0, B2 = 0, *A = 0, *B = 0; err = 0; numSegsA = _GetHandleSize((Handle)*A1) / sizeof(Segment); numSegsB = _GetHandleSize((Handle)*B1) / sizeof(Segment); A2 = (SEGMENTH)_NewHandle(numSegsA * sizeof(Segment)); if (_MemError()) { TechError("CombinePolygonPieces()", "_NewHandle()", 0); goto done; } for (i = 0 ; i < numSegsA ; i++) INDEXH(A2, i) = INDEXH(*A1, i); A = &A2; B2 = (SEGMENTH)_NewHandle(numSegsB * sizeof(Segment)); if (_MemError()) { TechError("CombinePolygonPieces()", "_NewHandle()", 0); goto done; } for (i = 0 ; i < numSegsB ; i++) INDEXH(B2, i) = INDEXH(*B1, i); B = &B2; for (i = 0 ; i < numSegsA ; i++) for (j = 0 ; j < numSegsB ; j++) if (SegmentTouchesSegment(INDEXH(*A, i), INDEXH(*B, j)) && !SameSegmentEndPoints(INDEXH(*A, i), INDEXH(*B, j))) { m = PointOfIntersection(INDEXH(*A, i), INDEXH(*B, j)); if (err = InsertSegment(A, &numSegsA, i, m)) goto done; if (err = InsertSegment(B, &numSegsB, j, m)) goto done; } C = (SEGMENTH)_NewHandle(0); if (_MemError()) { TechError("CombinePolygonPieces()", "_NewHandle()", 0); goto done; } for (i = 0 ; i < numSegsA ; i++) { m = Midpoint(INDEXH(*A, i)); if ((keepAinB && PointInPolygon(m, *B, numSegsB, TRUE)) || (keepAnotinB && !PointInPolygon(m, *B, numSegsB, TRUE))) if (err = AddSegment(&C, &numSegsC, INDEXH(*A, i))) goto done; } for (j = 0 ; j < numSegsB ; j++) { m = Midpoint(INDEXH(*B, j)); if ((keepBinA && PointInPolygon(m, *A, numSegsA, TRUE)) || (keepBnotinA && !PointInPolygon(m, *A, numSegsA, TRUE))) if (err = AddSegment(&C, &numSegsC, INDEXH(*B, j))) goto done; } SortSegments(C, numSegsC); done: if (A2) DisposeHandle((Handle)A2); if (B2) DisposeHandle((Handle)B2); if (err && C) DisposeHandle((Handle)C); return err ? 0 : C; }
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.; } } 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;*/ 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;*/ 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;*/ 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; }