avtLegacyStreamlineFilter::avtLegacyStreamlineFilter()
{
    stepLength = 1.;
    maxTime = 100.;
    showStart = true;
    radius = 0.125;
    pointDensity = 1;
    coloringMethod = STREAMLINE_COLOR_SPEED;
    displayMethod = STREAMLINE_DISPLAY_LINES;
    streamlineDirection = VTK_INTEGRATE_FORWARD;

    //
    // Initialize source values.
    //
    sourceType = STREAMLINE_SOURCE_POINT;
    INIT_POINT(pointSource, 0., 0., 0.);
    INIT_POINT(lineStart, 0., 0., 0.);
    INIT_POINT(lineEnd, 1., 0., 0.);
    INIT_POINT(planeOrigin, 0., 0., 0.);
    INIT_POINT(planeNormal, 0., 0., 1.);
    INIT_POINT(planeUpAxis, 0., 1., 0.);
    planeRadius = 1.4142136;
    INIT_POINT(sphereOrigin, 0., 0., 0.);
    sphereRadius = 1.;
    INIT_POINT(boxExtents, 0., 1., 0.);
    INIT_POINT(boxExtents+3, 1., 0., 1.);
    useWholeBox = false;

    // Set all of the filters to 0.
    streamline = 0;
    tubes = 0;
    ribbons = 0;
}
void yprToTrans(const YPRTrans* ypr, RotMat o){
	/*
	 * In our coordinates, yaw = y, pitch = x, roll = z
	 * We will compose our rotations as Y_1 X_2 Z_3
	 */
	const float yaw = ypr->yaw,
	pitch = ypr->pitch,
	roll = ypr->roll,
	c1 = cos(yaw),	s1 = sin(yaw),
	c2 = cos(pitch),s2 = sin(pitch),
	c3 = cos(roll),	s3 = sin(roll);
	
	INIT_POINT(o[0], c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3, c2*s1);
	INIT_POINT(o[1], c2*s3, c2*c3, -s2);
	INIT_POINT(o[2], c1*s2*s3 - c3 * s1, c1*c3*s2 + s1*s3, c1*c2);
}
void rotateTrans(const Point *p, Point *o, const RotMat rot) {
	Point tmp;
	INIT_POINT(tmp,
			   dot(p,rot + 0),
			   dot(p,rot + 1),
			   dot(p,rot + 2));
	*o = tmp;
}
void scaleProj(const Point *p, Point *o, const float * scale){
	Point tmp;
	INIT_POINT(tmp,
			   *scale * p->x,
			   *scale * p->y,
			   *scale * p->z);
	*o = tmp;
}
void snapOntoProj(const Point *p, Point *o, const OntoProj * state){
	Point tmp;
	const float x = state->zeroCoord == offsetof(Point, x) ? state->planeValue : p->x,
	y = state->zeroCoord == offsetof(Point, y) ? state->planeValue : p->y,
	z = state->zeroCoord == offsetof(Point, z) ? state->planeValue : p->z;
	INIT_POINT(tmp,roundOwn(x),roundOwn(y),roundOwn(z));
	*o = tmp;
}
void orthoProj(const Point *p, Point *o, const Edge * viewportSpan){
	const Point * min = (*viewportSpan)[START];
	const Point * max = (*viewportSpan)[END];
	const float l = min->x,
	r = max->x,
	b = min->y,
	t = max->y,
	n = min->z,
	f = max->z,
	x = (2*p->x - (l + r))/(r-l),
	y = (2*p->y - (t + b))/(t-b),
	z = (-2*p->z + (f + n))/(f-n);
	Point tmp;
	INIT_POINT(tmp, x,y,z);
	*o = tmp;
}
void render(PaletteRef *raster, int lineWidth, int numLines, const rb_red_blk_tree *scanLinePrimBuckets){
	static OntoProj screenPlaneData = {offsetof(Point, z), 0};
	static const Transformation screenPlane = {(TransformationF)(&snapOntoProj), &screenPlaneData};
	{
		int line;
		rb_red_blk_tree activePrimSet;
		ActiveEdgeList ael = freshAEL();
		rb_red_blk_map_tree inFlags;
		rb_red_blk_tree deFlags;
		/* This ensures that both trees are initialized and in a cleared state */
		RBTreeMapInit(&inFlags, pointerDiffF, NULL, &RBMapNodeAlloc, NULL);
		RBTreeInit(&deFlags, pointerDiffF, NULL, &RBNodeAlloc);
		RBTreeInit(&activePrimSet, pointerDiffF, NULL, &RBNodeAlloc);
		dPrintf(("Scanning line: 0\n"));
		for(line = 0; line < numLines; (++line), (raster += lineWidth)) {
			rb_red_blk_node *primIt, *p = NULL, *nextP;
			dPrintf(("\tUpdating activePrimSet\n"));
			for (primIt = activePrimSet.first; primIt != activePrimSet.sentinel; (p = primIt), (primIt = nextP)) {
				const Primitive* prim = primIt->key;
				const int top = roundOwn(topMostPoint(prim));
				nextP = TreeSuccessor(&activePrimSet, primIt);
				if(top < line){
#ifndef NDEBUG
					{
						const int bottom = roundOwn(bottomMostPoint(prim));
						dPrintf(("\t\t%d -> %d ( %s ) is not valid here: %d\n",top,bottom,fmtColor(prim->color), line));
					}
#endif
					RBDelete(&activePrimSet, primIt);
					primIt = p; /* We don't want to advance p into garbage data */
				}
			}
			{
				const rb_red_blk_tree *bucket = scanLinePrimBuckets + line;
				const rb_red_blk_node *node;
				for(node = bucket->first; node != bucket->sentinel; node = TreeSuccessor(bucket, node)) {
					Primitive * prim = node->key;
#ifndef NDEBUG
					{
						const int top = roundOwn(topMostPoint(prim)),
						bottom = roundOwn(bottomMostPoint(prim));
						dPrintf(("\t\t%d -> %d ( %s ) is added here: %d\n",top,bottom,fmtColor(prim->color), line));
					}
#endif
					RBTreeInsert(&activePrimSet, prim);
				}
			}
			stepEdges(&ael, &activePrimSet);
			{
				int curPixel = 0;
				const Primitive *curDraw = NULL;
				EdgeListEntry *nextEdge;
				LinkN* i = ael.activeEdges;
				if(i){
					nextEdge = i->data;
					while(nextEdge && curPixel < lineWidth){
						EdgeListEntry *const startEdge = nextEdge;
						Primitive *const startOwner = startEdge->owner;
						int startX = roundOwn(getSmartXForLine(startEdge, line)), nextX;
						rb_red_blk_map_node *inFlag = (rb_red_blk_map_node *)RBExactQuery((rb_red_blk_tree*)(&inFlags), startOwner);
						
						if(inFlag){
							static Point localPoints[6]; /* We don't recurse, so this is fine */
							static Edge flatHere = {localPoints, localPoints + 1},
							flatIn = {localPoints + 2, localPoints + 3},
							vert = {localPoints + 4, localPoints + 5};
							const EdgeListEntry *const edgeInEntry = inFlag->info;
							Point **const edgeHere = startEdge->edge, **edgeIn = edgeInEntry->edge;
							const Point *const s = edgeHere[START],
							*const e = edgeHere[END];
							Point here;
							bool sV, eV, v;
							float dotH, dotIn;
							transformEdge(&screenPlane, edgeHere, flatHere);
							transformEdge(&screenPlane, edgeIn, flatIn);
							INIT_POINT(here, startX, line, 0);
							sV = contains(edgeIn, s);
							eV = contains(edgeIn, e);
							v = (sV || eV) && contains(flatIn, &here) && contains(flatHere, &here) && (startOwner->arity != 1);
							vert[START] = &here;
							INIT_POINT(*(vert[END]), startX, line+1, 0);
							dotH = v ? dotEdge(vert, flatHere) : 0;
							dotIn = v ? dotEdge(vert, flatIn) : 0;
							if(!v || dotH * dotIn > 0){
								dPrintf(("\tNot *in* old %s at %f\n", fmtColor(startEdge->owner->color), getSmartXForLine(startEdge, line)));
								RBSetAdd(&deFlags, startOwner);
							} else {
								dPrintf(("\tFound horizontal vertex %s at %f. Don't delete it yet\n",fmtColor(startEdge->owner->color), getSmartXForLine(startEdge, line)));
							}
						} else {
							dPrintf(("\tNow *in* new %s at %f\n",fmtColor(startEdge->owner->color), getSmartXForLine(startEdge, line)));
							/* This might happen if a polygon is parallel to the x-axis */
							RBMapPut(&inFlags, startOwner, startEdge);
						}
						
						if(curPixel < startX){
							dPrintf(("\tcurPixel has fallen behind, dragging from %d to %d\n",curPixel, startX));
							curPixel = startX;
						}
						
						i = i->tail;
						if(i){
							nextEdge = i->data;
							nextX = roundOwn(getSmartXForLine(nextEdge, line));
							dPrintf(("\tNext edges @ x = %d from %s\n",nextX, fmtColor(nextEdge->owner->color)));
						} else {
							dPrintf(("\tNo more edges\n"));
							nextEdge = NULL;
							nextX = 0;
						}
						
						nextX = min(nextX, lineWidth);
						while ((!nextEdge && curPixel < lineWidth) || (curPixel < nextX)) {
							bool zFight = false, solitary = false;
							float bestZ = HUGE_VAL;
							const rb_red_blk_node *node;
							curDraw = NULL;
							dPrintf(("\tTesting depth:\n"));
							for(node = inFlags.tree.first; node != inFlags.tree.sentinel; node = TreeSuccessor((rb_red_blk_tree*)(&inFlags), node)) {
								const Primitive *prim = node->key;
								/* We need sub-pixel accuracy */
								const float testZ = getZForXY(prim, curPixel, line);
								if(testZ <= bestZ + PT_EPS){
									dPrintf(("\t\tHit: %f <= %f for %s\n",testZ, bestZ, fmtColor(prim->color)));
									if (CLOSE_ENOUGH(testZ, bestZ)) {
										if (prim->arity == 1) {
											zFight = curDraw && curDraw->arity == 1;
											curDraw = prim;
											solitary = RBSetContains(&deFlags, prim);
										} else {
											zFight = curDraw && curDraw->arity != 1;
										}
									} else {
										zFight = false;
										bestZ = testZ;
										curDraw = prim;
										solitary = RBSetContains(&deFlags, prim);
									}
								} else {
									dPrintf(("\t\tMiss: %f > %f for %s\n",testZ, bestZ, fmtColor(prim->color)));
								}
							}
							
							if(curDraw){
#ifndef NDEBUG
								if(nextEdge || solitary){
#endif
									const int drawWidth =  (zFight || solitary) ? 1 : ((nextEdge ? nextX : lineWidth) - curPixel),
									stopPixel = curPixel + min(lineWidth - curPixel,
															   max(0, drawWidth));
									const PaletteRef drawColor = /*(uint16_t)roundOwn(63 * bestZ / 100) << 5;*/decodeColor(curDraw->color);
									dPrintf(("Drawing %d @ (%d, %d)\n",drawWidth,curPixel,line));
									dPrintf(("Drawing %d @ (%d, %d)\n",stopPixel - curPixel,curPixel,line));
									while(curPixel < stopPixel){
										raster[curPixel++] = drawColor;
									}
#ifndef NDEBUG
								} else {
									dPrintf(("Warning: we probably shouldn't have to draw if there are no more edges to turn us off. Look for parity errors\n");
											RBTreeClear((rb_red_blk_tree*)&inFlags));
								}
#endif
							} else if(!inFlags.tree.size && nextEdge){
								/* fast forward, we aren't in any polys */
								dPrintf(("Not in any polys at the moment, fast-forwarding(1) to %d\n", nextX));
								curPixel = nextX;
							} else {
								/* Nothing left */
								dPrintf(("Nothing to draw at end of line\n"));
								curPixel = lineWidth;
							}
							
							for(node = deFlags.first; node != deFlags.sentinel; node = TreeSuccessor(&deFlags, node)){
								RBMapRemove(&inFlags, node->key);
							}
							RBTreeClear(&deFlags);
						}
						if (!inFlags.tree.size && nextEdge) {
							dPrintf(("Not in any polys at the moment, fast-forwarding(2) to %d\n", nextX));
							curPixel = nextX;
						}
					}
				}
			}
#ifndef NDEBUG
			{
				dPrintf(("Scanning line: %d\n", line+1));
				if(inFlags.tree.size){
					rb_red_blk_node *node;
					dPrintf(("\tGarbage left in inFlags:\n"));
					for (node = inFlags.tree.first; node != inFlags.tree.sentinel; node = TreeSuccessor((rb_red_blk_tree*)&inFlags, node)) {
						dPrintf(("\t\t%s\n",fmtColor(((const Primitive*)node->key)->color)));
					}
				}
			}
#endif
			RBTreeClear(&deFlags);
			RBTreeClear((rb_red_blk_tree*)(&inFlags));
		}
		RBTreeDestroy(&activePrimSet, false);
		RBTreeDestroy(&deFlags, false);
		RBTreeDestroy((rb_red_blk_tree*)(&inFlags), false);
	}