FlowArrow::FlowArrow(FlowCtx* flow_ctx, double x1, double y1, double x2, double y2, double w, double l, flow_eDrawType d_type) : ctx(flow_ctx), p_dest(flow_ctx, x2, y2), arrow_width(w), arrow_length(l), draw_type(d_type), line_width(1) { double p1_x, p1_y, p2_x, p2_y; if (fabs(x2 - x1) < DBL_EPSILON) { if (y1 > y2) { p1_x = x2 + w / 2; p1_y = y2 + l; p2_x = x2 - w / 2; p2_y = y2 + l; } else { p1_x = x2 + w / 2; p1_y = y2 - l; p2_x = x2 - w / 2; p2_y = y2 - l; } } else if (fabs(y2 - y1) < DBL_EPSILON) { if (x1 > x2) { p1_x = x2 + l; p1_y = y2 + w / 2; p2_x = x2 + l; p2_y = y2 - w / 2; } else { p1_x = x2 - l; p1_y = y2 - w / 2; p2_x = x2 - l; p2_y = y2 + w / 2; } } else { double d = sqrt((y1 - y2) * (y1 - y2) + (x1 - x2) * (x1 - x2)); p1_x = x2 + (x1 - x2) * l / d + (y1 - y2) * w / d / 2; p1_y = y2 + (y1 - y2) * l / d - (x1 - x2) * w / d / 2; p2_x = x2 + (x1 - x2) * l / d - (y1 - y2) * w / d / 2; p2_y = y2 + (y1 - y2) * l / d + (x1 - x2) * w / d / 2; } p1 = FlowPoint(flow_ctx, p1_x, p1_y); p2 = FlowPoint(flow_ctx, p2_x, p2_y); }
void FlowData::load() { if(!mReady) { Timer timer(true); XmlDocument * pointsDoc = new XmlDocument(dataSource); XmlElement rootNode = pointsDoc->rootNode(); if(rootNode.hasChildren()) { XmlElement tagNode = rootNode.findChild("tag"); XmlElement drawingNode = tagNode.findChild("drawing"); // Now get all the drawingNode's children.. and only worry about the stroke nodes. if(drawingNode.hasChildren()) { std::vector<XmlElement> strokeNodes = drawingNode.children(); // std::vector<XmlElement> strokeNodes = rootNode.xpath("//tag/drawing//stroke"); if(strokeNodes.size() > 0) { int totalPoints = 0; // Now declare some variables to reuse in our loop. FlowPoint lastPt(Vec2f::zero(), Vec2f::zero(), -1.f); for(std::vector<XmlElement>::iterator it = strokeNodes.begin(); it < strokeNodes.end(); it++) { XmlElement strokeNode = *it; if(strokeNode.name() == "stroke") { // Get all the point nodes. std::vector<XmlElement> pointNodes = strokeNode.children(); // Create a new stroke std::vector<FlowPoint> * stroke = new std::vector<FlowPoint>; for(std::vector<XmlElement>::iterator it2 = pointNodes.begin(); it2 < pointNodes.end(); it2++) { XmlElement ptNode = *it2; if(ptNode.name() == "pt") { std::string xVal = ptNode.findChild("x").value(); // float x = fromString( xVal ); float x = boost::lexical_cast<float>( xVal ); std::string yVal = ptNode.findChild("y").value(); // float y = fromString( yVal ); float y = boost::lexical_cast<float>( yVal ); std::string timeVal = ptNode.findChild("time").value(); // float time = fromString( timeVal ); float time = boost::lexical_cast<float>( timeVal ); x = mRemapMinX + (mRemapMaxX - mRemapMinX) * x; y = mRemapMinY + (mRemapMaxY - mRemapMinY) * y; Vec2f pos(x, y); Vec2f vel; if(lastPt.time > -1) { vel.x = pos.x - lastPt.getX(); vel.y = pos.y - lastPt.getY(); } FlowPoint pt(pos, vel, time); bool shouldAddPoint = false; if(ignoreRedundantPositions == true) { if(lastPt.time > -1) { if(pt.getX() != lastPt.getX() && pt.getY() != lastPt.getY()) { shouldAddPoint = true; } } else { shouldAddPoint = true; } } else { shouldAddPoint = true; } if(shouldAddPoint) { totalPoints++; stroke->push_back(pt); lastPt = FlowPoint(pt.pos, pt.vel, pt.time); } } } // Now see if our stroke is long enough. if(stroke->size() > minNumberOfPointsInStroke) { mStrokes.push_back(stroke); } } } // We're done. timer.stop(); std::cout << "FlowData :: GML file parsing complete. Elapsed seconds: " << toString( timer.getSeconds() ) << std::endl; std::cout << "FlowData :: Total number of points: " << totalPoints << std::endl; std::cout << "FlowData :: Number of strokes: " << mStrokes.size() << std::endl; if(mStrokes.size() > 0) mReady = true; } } } } }