Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
0
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");
				}
			}
		}
	}
}
Пример #5
0
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;}
}
Пример #6
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;
		}
	}
}
Пример #7
0
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;
}
Пример #8
0
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);
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
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;
}
Пример #13
0
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;
}
Пример #14
0
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;
}
Пример #15
0
//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;
}
Пример #16
0
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;
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
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++;
		}
	}
}
Пример #23
0
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]);
}
Пример #24
0
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;
}
Пример #25
0
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]);
}
Пример #26
0
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;
}
Пример #27
0
//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;
}
Пример #28
0
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;
}
Пример #29
0
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;
}
Пример #30
0
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;
}