/***********************************************************************//**
 * @brief Set nodes for a radians axis
 *
 * @param[in] index Axis index [0,...,axes()-1].
 *
 * @exception GException::out_of_range
 *            Axis index out of range.
 *
 * Set axis nodes so that each node is the lo mean of the lower and upper
 * bin boundary in radians, i.e.
 * \f[ n_i = \frac{\pi}{360} \times ({\rm LO}_i + {\rm HI}_i) \f]
 * where
 * \f$n_i\f$ is node \f$i\f$,
 * \f${\rm LO}_i\f$ is the lower bin boundary for bin \f$i\f$, and
 * \f${\rm HI}_i\f$ is the upper bin boundary for bin \f$i\f$.
 ***************************************************************************/
void GCTAResponseTable::axis_radians(const int& index)
{
    // Optionally check if the index is valid
    #if defined(G_RANGE_CHECK)
    if (index < 0 || index >= axes()) {
        throw GException::out_of_range(G_AXIS_RADIANS, index, axes()-1);
    }
    #endif

    // Get number of bins
    int bins = axis(index);

    // Allocate node values
    std::vector<double> axis_nodes(bins);

    // Compute nodes
    for (int i = 0; i < bins; ++i) {
        axis_nodes[i] = 0.5*(m_axis_lo[index][i] + m_axis_hi[index][i]) *
                        gammalib::deg2rad;
    }

    // Set node array
    m_axis_nodes[index] = GNodeArray(axis_nodes);

    // Return
    return;
}
示例#2
0
void QniteXYArtist::processData() {
  if (qMin(xValues().size(), yValues().size()) < 1) {
    return;
  }

  // get bounds
  qreal xLower = axes()->axisX()->lowerBound();
  qreal xUpper = axes()->axisX()->upperBound();
  qreal yLower = axes()->axisY()->lowerBound();
  qreal yUpper = axes()->axisY()->upperBound();

  // TODO: this should be improved. clipping should be done only when bounds
  // changes and tranforsm should always be performed
  QMap<int, qreal> xClipped;
  QMap<int, qreal> yClipped;
  // clip non visible data
  if (clipper() != nullptr) {
    clipper()->clip(m_xValues, m_yValues, xLower, xUpper, yLower, yUpper,
                    xClipped, yClipped);
  } else {
    xClipped = m_xValues;
    yClipped = m_yValues;
  }

  // map to display
  m_xMapped = xMapper()->mapTo(xLower, xUpper, 0, width(), xClipped);
  m_yMapped = yMapper()->mapTo(yLower, yUpper, 0, height(), yClipped, true);

  // TODO: this is ugly and inefficient. move into a pipelino or something
  // similar move to the output area
  m_xProcessed = m_xMapped.values();
  m_yProcessed = m_yMapped.values();
}
/***********************************************************************//**
 * @brief Return axis length
 *
 * @param[in] index Axis index [0,...,axes()-1].
 * @return Number of bins along the specified axis.
 *
 * @exception GException::out_of_range
 *            Axis index out of range.
 *
 * Returns the number of bins along the specified axis.
 ***************************************************************************/
int GCTAResponseTable::axis(const int& index) const
{
    // Optionally check if the index is valid
    #if defined(G_RANGE_CHECK)
    if (index < 0 || index >= axes()) {
        throw GException::out_of_range(G_AXIS, index, axes()-1);
    }
    #endif

    // Return axis length
    return (m_axis_lo[index].size());
}
/***********************************************************************//**
 * @brief Return upper bin boundary for bin in axis
 *
 * @param[in] index Axis index [0,...,axes()-1].
 * @param[in] bin Bin index (starting from 0).
 * @return Uppser bin boundary.
 *
 * @exception GException::out_of_range
 *            Axis or bin index out of range.
 *
 * Returns the upper boundary for a given bin of a given axis.
 ***************************************************************************/
double GCTAResponseTable::axis_hi(const int& index, const int& bin) const
{
    // Optionally check if the index is valid
    #if defined(G_RANGE_CHECK)
    if (index < 0 || index >= axes() ||
        bin   < 0 || bin   >= m_axis_hi[index].size()) {
        throw GException::out_of_range(G_AXIS_HI, index, bin,
                                       axes()-1, m_axis_hi[index].size()-1);
    }
    #endif

    // Return bin boundary
    return (m_axis_hi[index][bin]);
}
示例#5
0
        void RotateHandle::renderRing(Model::RotateHandleHit* hit, Renderer::Vbo& vbo, Renderer::RenderContext& context, float angle) {
            assert(hit != NULL);

            Vec3f xAxis, yAxis, zAxis;
            axes(context.camera().position(), xAxis, yAxis, zAxis);

            Renderer::ActivateShader shader(context.shaderManager(), Renderer::Shaders::HandleShader);

            Mat4f rotation;
            if (hit->hitArea() == Model::RotateHandleHit::HAXAxis) {
                rotation = rotationMatrix(angle, Vec3f::PosX);
                Renderer::ApplyModelMatrix applyRotation(context.transformation(), rotation);

                shader.setUniformVariable("Color", Color(1.0f, 1.0f, 1.0f, 0.25f));
                Renderer::RingFigure(Axis::AX, yAxis, zAxis, m_ringRadius, m_ringThickness, 8).render(vbo, context);
                shader.setUniformVariable("Color", Color(1.0f, 1.0f, 1.0f, 1.0f));
                Renderer::CircleFigure(Axis::AX, 0.0f, 2.0f * Math<float>::Pi, m_ringRadius + m_ringThickness, 32, false).render(vbo, context);
            } else if (hit->hitArea() == Model::RotateHandleHit::HAYAxis) {
                rotation = rotationMatrix(angle, Vec3f::PosY);
                Renderer::ApplyModelMatrix applyRotation(context.transformation(), rotation);

                shader.setUniformVariable("Color", Color(1.0f, 1.0f, 1.0f, 0.25f));
                Renderer::RingFigure(Axis::AY, xAxis, zAxis, m_ringRadius, m_ringThickness, 8).render(vbo, context);
                shader.setUniformVariable("Color", Color(1.0f, 1.0f, 1.0f, 1.0f));
                Renderer::CircleFigure(Axis::AY, 0.0f, 2.0f * Math<float>::Pi, m_ringRadius + m_ringThickness, 32, false).render(vbo, context);
            } else {
                rotation = rotationMatrix(angle, Vec3f::PosZ);
                Renderer::ApplyModelMatrix applyRotation(context.transformation(), rotation);

                shader.setUniformVariable("Color", Color(1.0f, 1.0f, 1.0f, 0.25f));
                Renderer::RingFigure(Axis::AZ, xAxis, yAxis, m_ringRadius, m_ringThickness, 8).render(vbo, context);
                shader.setUniformVariable("Color", Color(1.0f, 1.0f, 1.0f, 1.0f));
                Renderer::CircleFigure(Axis::AZ, 0.0f, 2.0f * Math<float>::Pi, m_ringRadius + m_ringThickness, 32, false).render(vbo, context);
            }
        }
示例#6
0
void NavMeshAgent::syncToNode()
{
    const dtCrowdAgent *agent = nullptr;
    if (_crowd){
        agent = _crowd->getAgent(_agentID);
    }

    if (agent){
        Mat4 wtop;
        Vec3 pos;
        if (_owner->getParent())
            wtop = _owner->getParent()->getWorldToNodeTransform();
        wtop.transformPoint(Vec3(agent->npos[0], agent->npos[1], agent->npos[2]), &pos);
        _owner->setPosition3D(pos);
        _state = agent->state;
        if (_needAutoOrientation){
            if (std::abs(agent->vel[0]) > 0.3f || std::abs(agent->vel[1]) > 0.3f || std::abs(agent->vel[2]) > 0.3f)
            {
                Vec3 axes(_rotRefAxes);
                axes.normalize();
                Vec3 dir;
                wtop.transformVector(Vec3(agent->vel[0], agent->vel[1], agent->vel[2]), &dir);
                dir.normalize();
                float cosTheta = Vec3::dot(axes, dir);
                Vec3 rotAxes;
                Vec3::cross(axes, dir, &rotAxes);
                Quaternion rot = Quaternion(rotAxes, acosf(cosTheta));
                _owner->setRotationQuat(rot);
            }
        }
    }
}
示例#7
0
void NudgeSelection (ENudgeDirection direction, float fAmount, EViewType viewtype)
{
	AxisBase axes(AxisBase_forViewType(viewtype));
	Vector3 view_direction(-axes.z);
	Vector3 nudge(AxisBase_axisForDirection(axes, direction) * fAmount);
	GlobalSelectionSystem().NudgeManipulator(nudge, view_direction);
}
AMPIC887AxisCollection AMPIC887ConsoleCommandParser::axesFromCommandString(const QString &axisArguments,
        AMPIC887AxisCollection::InitializationState stateIfEmpty)
{

    QStringList axisArgumentList = commandArguments(axisArguments);

    if(axisArgumentList.isEmpty()) {
        return AMPIC887AxisCollection(stateIfEmpty);

    }

    AMPIC887AxisCollection axes(AMPIC887AxisCollection::EmptyCollection);

    for(int iAxis = 0, argCount = axisArgumentList.count();
            iAxis < argCount;
            ++iAxis) {

        QString axisString = axisArgumentList.at(iAxis);

        if(axisString.length() != 1) {
            axes.append(AMGCS2::UnknownAxis);
        } else {
            axes.append(AMGCS2Support::characterToAxis(axisString.at(0)));
        }
    }

    return axes;
}
示例#9
0
bool SATCollision::IsColliding(const std::vector<sf::Vector2f>& b1, const std::vector<sf::Vector2f>& b2)
{
	std::vector<sf::Vector2f> axes(4);
	axes[0] = b1[1] - b1[0];
	axes[1] = b1[2] - b1[0];
	axes[2] = b2[1] - b2[0];
	axes[3] = b2[2] - b2[0];

	for(unsigned int axis = 0; axis < axes.size(); axis++) {
		float maxb1 = -FLT_MAX, minb1 = FLT_MAX;
		float maxb2 = -FLT_MAX, minb2 = FLT_MAX;

		for(unsigned int i = 0; i < b1.size(); i++) {
			float projection = dot(Project(b1[i], axes[axis]), axes[axis]);
			maxb1 = std::max(maxb1, projection);
			minb1 = std::min(minb1, projection);
		}
		for(unsigned int i = 0; i < b2.size(); i++) {
			float projection = dot(Project(b2[i], axes[axis]), axes[axis]);
			maxb2 = std::max(maxb2, projection);
			minb2 = std::min(minb2, projection);
		}

		if((minb1 > maxb2 && minb1 > minb2) || (minb2 > maxb1 && minb2 > minb1)) {
			return false;
		}
	}

	return true;
}
示例#10
0
文件: graph.c 项目: andreiw/polaris
int
main(int argc, char **argv)
{

	space(0,0,4096,4096);
	init(&xd);
	init(&yd);
	xd.xsize = yd.xsize = 1.;
	xx = (struct val *)malloc((unsigned)sizeof(struct val));
	labsarr = malloc(1);
	labsarr[labsiz++] = 0;
	setopt(argc,argv);
	if(erasf)
		erase();
	readin();
	transpose();
	scale(&xd,(struct val *)&xx->xv);
	scale(&yd,(struct val *)&xx->yv);
	axes();
	title();
	plot();
	move(1,1);
	closevt();
	return(0);
}
示例#11
0
QVector<QVector3D> OBB::getAxes() const
{
	QVector<QVector3D> axes(3);
	axes[0] = QVector3D(x_axis);
	axes[1] = QVector3D(y_axis);
	axes[2] = QVector3D(z_axis);

	return axes;
}
示例#12
0
void QniteGridPainter::synchronize(QNanoQuickItem *item) {
  qCDebug(qnitegridpainter) << "synchronizing grid";

  auto grid = static_cast<QniteGrid *>(item);
  if (grid != Q_NULLPTR) {
    // make a local copy of the pen
    m_pen = grid->pen()->data();

    // copy the tick values from both axes
    m_xs = grid->axes()->axisX()->majorTicks();
    m_ys = grid->axes()->axisY()->majorTicks();

    m_xsize = grid->axes()->axisX()->size();
    m_ysize = grid->axes()->axisY()->size();

    m_drawX = grid->drawXAxes();
    m_drawY = grid->drawYAxes();
  }
}
示例#13
0
void Projection::render(QGraphicsScene *scene) {
    QMatrix4x4 matrix = transformMatrix()
            * scaleMatrix(scene->width(), -scene->height(), 1)
            * shiftMatrix(0, scene->height(), 0);

    scene->clear();

    renderSegments(scene, unitCube(), matrix);
    renderSegments(scene, axes(), matrix);
}
示例#14
0
AMDetector::operator AMMeasurementInfo() {
    return AMMeasurementInfo(name(), description(), units(), axes());
    // This is code included from the previous AMDetector(Info) system. This may be important for the transition. [DKC January 14th, 2013]
    /*
    if(!description().isEmpty())
    	return AMMeasurementInfo(description().remove(" "), description(), units(), axes());
    else
    	return AMMeasurementInfo(name(), name(), units(), axes());
    */
}
示例#15
0
std::vector<long> FitsFile::GetColumnDimensions(int columnIndex)
{
	CheckOpen();
	int naxis = 0, status = 0;
	constexpr int maxdim = 10;
	std::vector<long> axes(maxdim, 0);
	fits_read_tdim(_fptr, columnIndex, maxdim, &naxis, axes.data(), &status);
	CheckStatus(status);
	axes.resize(naxis);
	return axes;
}
示例#16
0
        Model::RotateHandleHit* RotateHandle::pick(const Rayf& ray) {
            Vec3f xAxis, yAxis, zAxis;
            axes(ray.origin, xAxis, yAxis, zAxis);
            Model::RotateHandleHit* closestHit = NULL;

            closestHit = selectHit(closestHit, pickRing(ray, xAxis, yAxis, zAxis, Model::RotateHandleHit::HAXAxis));
            closestHit = selectHit(closestHit, pickRing(ray, yAxis, xAxis, zAxis, Model::RotateHandleHit::HAYAxis));
            closestHit = selectHit(closestHit, pickRing(ray, zAxis, xAxis, yAxis, Model::RotateHandleHit::HAZAxis));

            if (!locked())
                setLastHit(closestHit);
            return closestHit;
        }
示例#17
0
/***********************************************************************//**
 * @brief Read axes definitions from FITS HDU
 *
 * @param[in] hdu Response table HDU.
 *
 * @exception GCTAException::bad_rsp_table_format
 *            Incompatible axes columns found.
 *
 * Reads the lower and upper boundaries for all response table axes from the
 * FITS HDU. The method verifies if the lower and upper boundary axes have
 * the same vector dimensions. 
 *
 * The method also allocates the nodes for each axis, assuming that axis will
 * be used linearily, where each node is given by the linear mean of the
 * lower and upper boundary. In case that the axis should be used
 * logarithmically, the method axis_log10() can be used to change to a
 * logarithmic scale. The axis_linear() can be used to switch back to a
 * linear scale.
 *
 * This method sets the following members:
 *    m_axis_lo - Axes lower boundaries
 *    m_axis_hi - Axes upper boundaries
 *    m_axis_nodes - Axes mean values
 *
 * In case that the HDU pointer is not valid (NULL), this method clears the
 * axes boundaries and does nothing else.
 ***************************************************************************/
void GCTAResponseTable::read_axes(const GFitsTable& hdu)
{
    // Clear axes arrays
    m_axis_lo.clear();
    m_axis_hi.clear();
    m_axis_nodes.clear();
    
    // Loop over all dimensions
    for (int i = 0; i < axes(); ++i) {

        // Get pointers to table columns
        const GFitsTableCol* col_lo = hdu[m_colname_lo[i]];
        const GFitsTableCol* col_hi = hdu[m_colname_hi[i]];

        // Extract number of bins. Make sure that both columns have the
        // same number of bins
        int num = col_lo->number();
        if (num != col_hi->number()) {
            std::string message = "Incompatible number of bins found"
                                  " for columns '"+m_colname_lo[i]+"'"+
                                  " ("+gammalib::str(num)+") and '"+
                                  m_colname_hi[i]+"' ("+
                                  gammalib::str(col_hi->number())+".";
            throw GCTAException::bad_rsp_table_format(G_READ_AXES,
                                                      message);
        }

        // Initialise axis and node arrays
        std::vector<double> axis_lo(num);
        std::vector<double> axis_hi(num);
        std::vector<double> axis_nodes(num);

        // Copy axis information into arrays
        for (int k = 0; k < num; ++k) {
            axis_lo[k]    = col_lo->real(0,k);
            axis_hi[k]    = col_hi->real(0,k);
            axis_nodes[k] = 0.5*(axis_lo[k] + axis_hi[k]);
        }

        // Push axis array on storage
        m_axis_lo.push_back(axis_lo);
        m_axis_hi.push_back(axis_hi);

        // Create node array
        m_axis_nodes.push_back(GNodeArray(axis_nodes));

    } // endfor: looped over all dimensions

    // Return
    return;
}
示例#18
0
/***********************************************************************//**
 * @brief Print response table information
 *
 * @param[in] chatter Chattiness (defaults to NORMAL).
 * @return String containing response table information.
 *
 * Puts CTA response table information into a std::string object for
 * printing.
 ***************************************************************************/
std::string GCTAResponseTable::print(const GChatter& chatter) const
{
    // Initialise result string
    std::string result;

    // Continue only if chatter is not silent
    if (chatter != SILENT) {

        // Append header
        result.append("=== GCTAResponseTable ===");

        // Append information
        result.append("\n"+gammalib::parformat("Dimension") +
                      gammalib::str(axes()));
    
        // Append axes information
        for (int i = 0; i < axes(); ++i) {
            result.append("\n"+gammalib::parformat("Axis " +
                          gammalib::str(i)));
            result.append(gammalib::str(axis(i)));
            result.append(" ["+m_colname_lo[i]);
            result.append(", ");
            result.append(m_colname_hi[i]+"]");
        }

        // Append parameter information
        for (int i = 0; i < size(); ++i) {
            result.append("\n"+gammalib::parformat("Parameter " +
                          gammalib::str(i)));
            result.append(m_colname_par[i]);
        }

    } // endif: chatter was not silent

    // Return result
    return result;
}
示例#19
0
文件: main.cpp 项目: jepessen/wplot
int main(int argc, char *argv[])
{
	std::cout << "Styled text inset demo" << std::endl;
	QApplication a(argc, argv);
	WPlot::CartesianPlot2D* plot2D(new WPlot::CartesianPlot2D);
	WPlot::Ticks2D::Ptr ticks(new WPlot::Ticks2D);
	WPlot::Axes2D::Ptr axes(new WPlot::Axes2D);
	ticks->setOrigin(150.0, 200.0);
	ticks->setPrimaryTickLength(20);
	ticks->setEnableLabels(true);
	axes->setTicks(ticks);
	plot2D->setPadding(25, WPlot::Padding::PIXELS);
	plot2D->setPlotLimits(-3.3, 7.5, -2, 4.3);
	plot2D->addAxes(axes);
	plot2D->show();
	return a.exec();
}
示例#20
0
/***********************************************************************//**
 * @brief Read parameter cubes
 *
 * @param[in] hdu Response table HDU.
 *
 * @exception GCTAException::bad_rsp_table_format
 *            Parameter vector of bad size encountered.
 *
 * Reads the parameter cubes from the response table. The method also sets
 * the data members m_npars (number of parameters) and m_nelements (number
 * of elements per parameter).
 *
 * This method sets the following members:
 *    m_pars - Parameter values
 *    m_nelements - Number of elements per parameter
 *
 * In case that the HDU pointer is not valid (NULL), this method clears the
 * axes boundaries and does nothing else.
 ***************************************************************************/
void GCTAResponseTable::read_pars(const GFitsTable& hdu)
{
    // Clear parameter cubes
    m_pars.clear();
    
    // Compute expected cube size
    m_nelements = axis(0);
    for (int i = 1; i < axes(); ++i) {
        m_nelements *= axis(i);
    }
    
    // Loop over all parameter cubes
    for (int i = 0; i < size(); ++i) {

        // Get pointer to table column
        const GFitsTableCol* col = hdu[m_colname_par[i]];

        // Extract number of bins. Verify that the number of bins
        // corresponds to the expectation.
        int num = col->number();
        if (num != m_nelements) {
            std::string message = "Parameter vector '"+m_colname_par[i]+
                                  "' has wrong size "+gammalib::str(num)+
                                  " (expected"+
                                  gammalib::str(m_nelements)+").";
            throw GCTAException::bad_rsp_table_format(G_READ_PARS,
                                                      message);
        }

        // Initialise parameter cube
        std::vector<double> pars(num);

        // Copy parameter values
        for (int k = 0; k < num; ++k) {
            pars[k] = col->real(0,k);
        }

        // Push cube into storage
        m_pars.push_back(pars);

    } // endfor: looped over all parameter cubes

    // Return
    return;
}
示例#21
0
// Specialised overload, called by the general nudgeSelected() routine
void nudgeSelected(ENudgeDirection direction, float amount, EViewType viewtype)
{
	AxisBase axes(AxisBase_forViewType(viewtype));

	Vector3 view_direction(-axes.z);
	Vector3 nudge(AxisBase_axisForDirection(axes, direction) * amount);

	if (GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eTranslate ||
        GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag ||
        GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip)
    {
        GlobalSelectionSystem().translateSelected(nudge);

        // In clip mode, update the clipping plane
        if (GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip)
        {
            GlobalClipper().update();
        }
    }
}
示例#22
0
        void RotateHandle::render(Model::RotateHandleHit* hit, Renderer::Vbo& vbo, Renderer::RenderContext& renderContext, float angle) {
            Preferences::PreferenceManager& prefs = Preferences::PreferenceManager::preferences();
            const float distance = renderContext.camera().distanceTo(position());
            const float factor = prefs.getFloat(Preferences::HandleScalingFactor) * distance;

            const Mat4f matrix = translationMatrix(position()) * scalingMatrix(factor);
            Renderer::ApplyModelMatrix applyTranslation(renderContext.transformation(), matrix);

            glDisable(GL_DEPTH_TEST);
            glDisable(GL_CULL_FACE);
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

            Renderer::SetVboState activateVbo(vbo, Renderer::Vbo::VboActive);
            if (hit != NULL) {
                renderAxis(hit, vbo, renderContext);
                renderRing(hit, vbo, renderContext, angle);
            } else {
                Vec3f xAxis, yAxis, zAxis;
                axes(renderContext.camera().position(), xAxis, yAxis, zAxis);

                Renderer::ActivateShader coloredShader(renderContext.shaderManager(), Renderer::Shaders::ColoredHandleShader);

                Renderer::AxisFigure axisFigure(m_axisLength);
                axisFigure.setAxes(true, true, true);
                axisFigure.setXColor(prefs.getColor(Preferences::XColor));
                axisFigure.setYColor(prefs.getColor(Preferences::YColor));
                axisFigure.setZColor(prefs.getColor(Preferences::ZColor));
                axisFigure.render(vbo, renderContext);

                Renderer::ActivateShader shader(renderContext.shaderManager(), Renderer::Shaders::HandleShader);
                shader.setUniformVariable("Color", Color(1.0f, 1.0f, 1.0f, 0.25f));

                Renderer::RingFigure(Axis::AX, yAxis, zAxis, m_ringRadius, m_ringThickness, 8).render(vbo, renderContext);
                Renderer::RingFigure(Axis::AY, xAxis, zAxis, m_ringRadius, m_ringThickness, 8).render(vbo, renderContext);
                Renderer::RingFigure(Axis::AZ, xAxis, yAxis, m_ringRadius, m_ringThickness, 8).render(vbo, renderContext);
            }

            glEnable(GL_CULL_FACE);
            glEnable(GL_DEPTH_TEST);
        }
示例#23
0
文件: patches.c 项目: mooseman/Vogle
main()
{
	char	dev[20];
	int	i;

	fprintf(stderr,"Enter device: ");
	gets(dev);

	vinit(dev);

	color(BLACK);
	clear();

	/*
	 * Set up two viewports (They actually overlap)
	 */

	viewport(-1.0, 0.3, -1.0, 0.3);
	ortho(-2.0, 5.0, -2.0, 5.0, -2.0, 5.0);
	lookat(0.0, 0.0, 0.0, -3.0, 2.0, -4.0, 0.0);
	/*
	 * Save it 
	 */
	pushviewport();
	pushmatrix();

	viewport(-0.3, 1.0, -0.3, 1.0);
	ortho(-2.0, 5.0, -2.0, 5.0, -2.0, 5.0);
	lookat(0.0, 0.0, 0.0, 3.0, 2.0, -4.0, 0.0);

	textsize(0.4, 0.4);

	/*
	 * patchcurves provides a number of curves in the t and u
	 * directions. patchprecision gives the minimum number of line
	 * segments making up the curves in the t and u directions. The
	 * actual number of linesegments in t or u is equal to the closest
	 * integer multiple of the number of curves, > nsegs, in t or u,
	 * greater than or equal to the number set by patchprecision in u or
	 * t. eg. curves in t will be made up of 21 line segments so that we
	 * can match up the 7 curves in u; curves in u will have 24 as 4 by 5
	 * gives 20.
	 */
	patchcurves(4, 7);
	patchprecision(20, 20);

	for (i = 0; i < 4; i++) {

		axes();


		/*
		 * patchbasis sets the basis matrices for the t and u
		 * functions
		 * 
		 */
		patchbasis(basis[i], basis[i]);

		/* 
		 * Draw with viewport 2
		 */
		move(0.0, 4.0, 0.0);
		drawstr(labels[i]);

		/*
		 * now draw the patches according to the geometry matrices in
		 * x1, y1, and z1, x2, y2, z2.
		 */
		drawhull(x1, y1, z1);
		patch(x1, y1, z1);

		drawhull(x2, y2, z2);
		patch(x2, y2, z2);

		getkey();

		/*
		 * Now with viewport 1
		 */
		popviewport();
		popmatrix();

		axes();

		move(0.0, 4.0, 0.0);
		drawstr(labels[i]);

		/*
		 * now draw the patches according to the geometry matrices in
		 * x1, y1, and z1, x2, y2, z2.
		 */
		drawhull(x1, y1, z1);
		patch(x1, y1, z1);

		drawhull(x2, y2, z2);
		patch(x2, y2, z2);

		getkey();

		/*
		 * Save viewport 1 again and reset to viewport 2
		 */
		pushviewport();
		pushmatrix();

		viewport(-0.3, 1.0, -0.3, 1.0);
		ortho(-1.5, 5.0, -1.5, 5.0, -1.5, 5.0);
		lookat(0.0, 0.0, 0.0, 3.0, 2.0, -4.0, 0.0);

		color(BLACK);
		clear();
	}

	vexit();
}
示例#24
0
int CompareShapeFunctions(TPZCompElSide celsideA, TPZCompElSide celsideB)
{
    TPZGeoElSide gelsideA = celsideA.Reference();
    TPZGeoElSide gelsideB = celsideB.Reference();
    int sideA = gelsideA.Side();
    int sideB = gelsideB.Side();
    TPZCompEl *celA = celsideA.Element();
    TPZCompEl *celB = celsideB.Element();    TPZMultiphysicsElement *MFcelA = dynamic_cast<TPZMultiphysicsElement *>(celA);
    TPZMultiphysicsElement *MFcelB = dynamic_cast<TPZMultiphysicsElement *>(celB);
    TPZInterpolatedElement *interA = dynamic_cast<TPZInterpolatedElement *>(MFcelA->Element(0));
    TPZInterpolatedElement *interB = dynamic_cast<TPZInterpolatedElement *>(MFcelB->Element(0));
    
    TPZMaterialData dataA;
    TPZMaterialData dataB;
    interA->InitMaterialData(dataA);
    interB->InitMaterialData(dataB);
    TPZTransform<> tr = gelsideA.NeighbourSideTransform(gelsideB);
    TPZGeoEl *gelA = gelsideA.Element();
    TPZTransform<> trA = gelA->SideToSideTransform(gelsideA.Side(), gelA->NSides()-1);
    TPZGeoEl *gelB = gelsideB.Element();
    TPZTransform<> trB = gelB->SideToSideTransform(gelsideB.Side(), gelB->NSides()-1);
    
    int dimensionA = gelA->Dimension();
    int dimensionB = gelB->Dimension();
    
    int nSideshapeA = interA->NSideShapeF(sideA);
    int nSideshapeB = interB->NSideShapeF(sideB);
    int is;
    int firstShapeA = 0;
    int firstShapeB = 0;
    for (is=0; is<sideA; is++) {
        firstShapeA += interA->NSideShapeF(is);
    }
    for (is=0; is<sideB; is++) {
        firstShapeB += interB->NSideShapeF(is);
    }
    
    TPZIntPoints *intrule = gelA->CreateSideIntegrationRule(gelsideA.Side(), 4);
    int nwrong = 0;
    int npoints = intrule->NPoints();
    int ip;
    for (ip=0; ip<npoints; ip++) {
        TPZManVector<REAL,3> pointA(gelsideA.Dimension()),pointB(gelsideB.Dimension()), pointElA(gelA->Dimension()),pointElB(gelB->Dimension());
        REAL weight;
        intrule->Point(ip, pointA, weight);
        int sidedim = gelsideA.Dimension();
        TPZFNMatrix<9> jacobian(sidedim,sidedim),jacinv(sidedim,sidedim),axes(sidedim,3);
        REAL detjac;
        gelsideA.Jacobian(pointA, jacobian, jacinv, detjac, jacinv);
        TPZManVector<REAL,3> normal(3,0.), xA(3),xB(3);
        normal[0] = axes(0,1);
        normal[1] = -axes(0,0);
        tr.Apply(pointA, pointB);
        trA.Apply(pointA, pointElA);
        trB.Apply(pointB, pointElB);
        gelsideA.Element()->X(pointElA, xA);
        gelsideB.Element()->X(pointElB, xB);
        for (int i=0; i<3; i++) {
            if(fabs(xA[i]- xB[i])> 1.e-6) DebugStop();
        }
        int nshapeA = 0, nshapeB = 0;
        interA->ComputeRequiredData(dataA, pointElA);
        interB->ComputeRequiredData(dataB, pointElB);
        nshapeA = dataA.phi.Rows();
        nshapeB = dataB.phi.Rows();
        if(nSideshapeA != nSideshapeB) DebugStop();
        
        TPZManVector<REAL> shapesA(nSideshapeA), shapesB(nSideshapeB);
        int nwrongkeep(nwrong);
        int i,j;
        for(i=firstShapeA,j=firstShapeB; i<firstShapeA+nSideshapeA; i++,j++)
        {
            int Ashapeind = i;
            int Bshapeind = j;
            int Avecind = -1;
            int Bvecind = -1;
            // if A or B are boundary elements, their shapefunctions come in the right order
            if (dimensionA != sidedim) {
                Ashapeind = dataA.fVecShapeIndex[i].second;
                Avecind = dataA.fVecShapeIndex[i].first;
            }
            if (dimensionB != sidedim) {
                Bshapeind = dataB.fVecShapeIndex[j].second;
                Bvecind = dataB.fVecShapeIndex[j].first;
            }
            if (dimensionA != sidedim && dimensionB != sidedim) {
                // vefify that the normal component of the normal vector corresponds
                Avecind = dataA.fVecShapeIndex[i].first;
                Bvecind = dataB.fVecShapeIndex[j].first;
                REAL vecnormalA = dataA.fNormalVec(0,Avecind)*normal[0]+dataA.fNormalVec(1,Avecind)*normal[1];
                REAL vecnormalB = dataB.fNormalVec(0,Bvecind)*normal[0]+dataB.fNormalVec(1,Bvecind)*normal[1];
                if(fabs(vecnormalA-vecnormalB) > 1.e-6)
                {
                    nwrong++;
                    LOGPZ_ERROR(logger, "normal vectors aren't equal")
                }
                
            }
            shapesA[i-firstShapeA] = dataA.phi(Ashapeind,0);
            shapesB[j-firstShapeB] = dataB.phi(Bshapeind,0);
            REAL valA = dataA.phi(Ashapeind,0);
            REAL valB = dataB.phi(Bshapeind,0);
            REAL diff = valA-valB;
            REAL decision = fabs(diff)-1.e-6;
            if(decision > 0.)
            {
                nwrong ++;
                std::cout << "valA = " << valA << " valB = " << valB << " Avecind " << Avecind << " Bvecind " << Bvecind <<
                " Ashapeind " << Ashapeind << " Bshapeind " << Bshapeind <<
                " sideA " << sideA << " sideB " << sideB << std::endl;
                LOGPZ_ERROR(logger, "shape function values are different")
            }
示例#25
0
// This is essentially identical to the similarly-named helper function
// in gfx/thebes/gfxMacFont.cpp. Maybe we should put it somewhere that
// can be shared by both Moz2d and Thebes callers?
static CFDictionaryRef
CreateVariationDictionaryOrNull(CGFontRef aCGFont, uint32_t aVariationCount,
  const mozilla::gfx::ScaledFont::VariationSetting* aVariations)
{
  // Avoid calling potentially buggy variation APIs on pre-Sierra macOS
  // versions (see bug 1331683)
  if (!nsCocoaFeatures::OnSierraOrLater()) {
    return nullptr;
  }

  AutoRelease<CTFontRef>
    ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr));
  AutoRelease<CFArrayRef> axes(CTFontCopyVariationAxes(ctFont));
  if (!axes) {
    return nullptr;
  }

  CFIndex axisCount = CFArrayGetCount(axes);
  AutoRelease<CFMutableDictionaryRef>
    dict(CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
                                   &kCFTypeDictionaryKeyCallBacks,
                                   &kCFTypeDictionaryValueCallBacks));

  // Number of variation settings passed in the aVariations parameter.
  // This will typically be a very low value, so we just linear-search them.
  bool allDefaultValues = true;

  for (CFIndex i = 0; i < axisCount; ++i) {
    // We sanity-check the axis info found in the CTFont, and bail out
    // (returning null) if it doesn't have the expected types.
    CFTypeRef axisInfo = CFArrayGetValueAtIndex(axes, i);
    if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
      return nullptr;
    }
    CFDictionaryRef axis = static_cast<CFDictionaryRef>(axisInfo);

    CFTypeRef axisTag =
        CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey);
    if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
      return nullptr;
    }
    int64_t tagLong;
    if (!CFNumberGetValue(static_cast<CFNumberRef>(axisTag),
                          kCFNumberSInt64Type, &tagLong)) {
      return nullptr;
    }

    CFTypeRef axisName =
      CFDictionaryGetValue(axis, kCTFontVariationAxisNameKey);
    if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
      return nullptr;
    }

    // Clamp axis values to the supported range.
    CFTypeRef min = CFDictionaryGetValue(axis, kCTFontVariationAxisMinimumValueKey);
    CFTypeRef max = CFDictionaryGetValue(axis, kCTFontVariationAxisMaximumValueKey);
    CFTypeRef def = CFDictionaryGetValue(axis, kCTFontVariationAxisDefaultValueKey);
    if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
        !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
        !def || CFGetTypeID(def) != CFNumberGetTypeID()) {
      return nullptr;
    }
    double minDouble;
    double maxDouble;
    double defDouble;
    if (!CFNumberGetValue(static_cast<CFNumberRef>(min), kCFNumberDoubleType,
                          &minDouble) ||
        !CFNumberGetValue(static_cast<CFNumberRef>(max), kCFNumberDoubleType,
                          &maxDouble) ||
        !CFNumberGetValue(static_cast<CFNumberRef>(def), kCFNumberDoubleType,
                          &defDouble)) {
      return nullptr;
    }

    double value = defDouble;
    for (uint32_t j = 0; j < aVariationCount; ++j) {
      if (aVariations[j].mTag == tagLong) {
        value = std::min(std::max<double>(aVariations[j].mValue,
                                          minDouble),
                         maxDouble);
        if (value != defDouble) {
          allDefaultValues = false;
        }
        break;
      }
    }
    AutoRelease<CFNumberRef> valueNumber(CFNumberCreate(kCFAllocatorDefault,
                                                        kCFNumberDoubleType,
                                                        &value));
    CFDictionaryAddValue(dict, axisName, valueNumber);
  }

  if (allDefaultValues) {
    // We didn't actually set any non-default values, so throw away the
    // variations dictionary and just use the default rendering.
    return nullptr;
  }

  return dict.forget();
}
 void ParaxialTexCoordSystem::axes(const size_t index, Vec3& xAxis, Vec3& yAxis) {
     Vec3 temp;
     axes(index, xAxis, yAxis, temp);
 }
        void ParaxialTexCoordSystem::doTransform(const Plane3& oldBoundary, const Mat4x4& transformation, BrushFaceAttributes& attribs, bool lockTexture, const Vec3& oldInvariant) {
            const Vec3 offset     = transformation * Vec3::Null;
            const Vec3& oldNormal = oldBoundary.normal;
                  Vec3 newNormal  = transformation * oldNormal - offset;
            assert(Math::eq(newNormal.length(), 1.0));
            
            // fix some rounding errors - if the old and new texture axes are almost the same, use the old axis
            if (newNormal.equals(oldNormal, 0.01))
                newNormal = oldNormal;
            
            if (!lockTexture || attribs.xScale() == 0.0f || attribs.yScale() == 0.0f) {
                setRotation(newNormal, attribs.rotation(), attribs.rotation());
                return;
            }
            
            // calculate the current texture coordinates of the origin
            const Vec2f oldInvariantTexCoords = computeTexCoords(oldInvariant, attribs.scale()) + attribs.offset();

            // project the texture axes onto the boundary plane along the texture Z axis
            const Vec3 boundaryOffset     = oldBoundary.project(Vec3::Null, getZAxis());
            const Vec3 oldXAxisOnBoundary = oldBoundary.project(m_xAxis * attribs.xScale(), getZAxis()) - boundaryOffset;
            const Vec3 oldYAxisOnBoundary = oldBoundary.project(m_yAxis * attribs.yScale(), getZAxis()) - boundaryOffset;

            // transform the projected texture axes and compensate the translational component
            const Vec3 transformedXAxis = transformation * oldXAxisOnBoundary - offset;
            const Vec3 transformedYAxis = transformation * oldYAxisOnBoundary - offset;
            
            const Vec2f textureSize = attribs.textureSize();
            const bool preferX = textureSize.x() >= textureSize.y();

            /*
            const FloatType dotX = transformedXAxis.normalized().dot(oldXAxisOnBoundary.normalized());
            const FloatType dotY = transformedYAxis.normalized().dot(oldYAxisOnBoundary.normalized());
            const bool preferX = Math::abs(dotX) < Math::abs(dotY);
            */
            
            // obtain the new texture plane norm and the new base texture axes
            Vec3 newBaseXAxis, newBaseYAxis, newProjectionAxis;
            const size_t newIndex = planeNormalIndex(newNormal);
            axes(newIndex, newBaseXAxis, newBaseYAxis, newProjectionAxis);

            const Plane3 newTexturePlane(0.0, newProjectionAxis);
            
            // project the transformed texture axes onto the new texture projection plane
            const Vec3 projectedTransformedXAxis = newTexturePlane.project(transformedXAxis);
            const Vec3 projectedTransformedYAxis = newTexturePlane.project(transformedYAxis);
            assert(!projectedTransformedXAxis.nan() &&
                   !projectedTransformedYAxis.nan());

            const Vec3 normalizedXAxis = projectedTransformedXAxis.normalized();
            const Vec3 normalizedYAxis = projectedTransformedYAxis.normalized();
            
            // determine the rotation angle from the dot product of the new base axes and the transformed, projected and normalized texture axes
            float cosX = static_cast<float>(newBaseXAxis.dot(normalizedXAxis.normalized()));
            float cosY = static_cast<float>(newBaseYAxis.dot(normalizedYAxis.normalized()));
            assert(!Math::isnan(cosX));
            assert(!Math::isnan(cosY));

            float radX = std::acos(cosX);
            if (crossed(newBaseXAxis, normalizedXAxis).dot(newProjectionAxis) < 0.0)
                radX *= -1.0f;
            
            float radY = std::acos(cosY);
            if (crossed(newBaseYAxis, normalizedYAxis).dot(newProjectionAxis) < 0.0)
                radY *= -1.0f;
            
            // TODO: be smarter about choosing between the X and Y axis rotations - sometimes either
            // one can be better
            float rad = preferX ? radX : radY;
            
            // for some reason, when the texture plane normal is the Y axis, we must rotation clockwise
            if (newIndex == 4)
                rad *= -1.0f;
            
            const float newRotation = Math::correct(Math::normalizeDegrees(Math::degrees(rad)), 4);
            doSetRotation(newNormal, newRotation, newRotation);
            
            // finally compute the scaling factors
            Vec2f newScale = Vec2f(projectedTransformedXAxis.length(),
                                   projectedTransformedYAxis.length()).corrected(4);

            // the sign of the scaling factors depends on the angle between the new texture axis and the projected transformed axis
            if (m_xAxis.dot(normalizedXAxis) < 0.0)
                newScale[0] *= -1.0f;
            if (m_yAxis.dot(normalizedYAxis) < 0.0)
                newScale[1] *= -1.0f;
            
            // compute the parameters of the transformed texture coordinate system
            const Vec3 newInvariant = transformation * oldInvariant;

            // determine the new texture coordinates of the transformed center of the face, sans offsets
            const Vec2f newInvariantTexCoords = computeTexCoords(newInvariant, newScale);
            
            // since the center should be invariant, the offsets are determined by the difference of the current and
            // the original texture coordiknates of the center
            const Vec2f newOffset = attribs.modOffset(oldInvariantTexCoords - newInvariantTexCoords).corrected(4);
            
            assert(!newOffset.nan());
            assert(!newScale.nan());
            assert(!Math::isnan(newRotation));
            assert(!Math::zero(newScale.x()));
            assert(!Math::zero(newScale.y()));
            
            attribs.setOffset(newOffset);
            attribs.setScale(newScale);
            attribs.setRotation(newRotation);
        }
 void ParaxialTexCoordSystem::doSetRotation(const Vec3& normal, const float oldAngle, const float newAngle) {
     m_index = planeNormalIndex(normal);
     axes(m_index, m_xAxis, m_yAxis);
     rotateAxes(m_xAxis, m_yAxis, Math::radians(newAngle), m_index);
 }
示例#29
0
    static intptr_t instantiate(char *DYND_UNUSED(static_data), size_t DYND_UNUSED(data_size), char *DYND_UNUSED(data),
                                void *ckb, intptr_t ckb_offset, const ndt::type &dst_tp, const char *dst_arrmeta,
                                intptr_t DYND_UNUSED(nsrc), const ndt::type *src_tp, const char *const *src_arrmeta,
                                kernel_request_t kernreq, const eval::eval_context *DYND_UNUSED(ectx),
                                intptr_t DYND_UNUSED(nkwd), const nd::array *kwds,
                                const std::map<std::string, ndt::type> &DYND_UNUSED(tp_vars))
    {
        int flags;
        if (kwds[2].is_missing()) {
            flags = FFTW_ESTIMATE;
        } else {
            flags = kwds[2].as<int>();
        }

        nd::array shape = kwds[0];
        if (!shape.is_missing()) {
            if (shape.get_type().get_type_id() == pointer_type_id) {
                shape = shape;
            }
        }

        nd::array axes;
        if (!kwds[1].is_missing()) {
            axes = kwds[1];
            if (axes.get_type().get_type_id() == pointer_type_id) {
                axes = axes;
            }
        } else {
            axes = nd::range(src_tp[0].get_ndim());
        }

        const size_stride_t *src_size_stride = reinterpret_cast<const size_stride_t *>(src_arrmeta[0]);
        const size_stride_t *dst_size_stride = reinterpret_cast<const size_stride_t *>(dst_arrmeta);

        int rank = axes.get_dim_size();
        shortvector<fftw_iodim> dims(rank);
        for (intptr_t i = 0; i < rank; ++i) {
            intptr_t j = axes(i).as<intptr_t>();
            dims[i].n = shape.is_missing() ? src_size_stride[j].dim_size : shape(j).as<intptr_t>();
            dims[i].is = src_size_stride[j].stride / sizeof(fftw_src_type);
            dims[i].os = dst_size_stride[j].stride / sizeof(fftw_dst_type);
        }

        int howmany_rank = src_tp[0].get_ndim() - rank;
        shortvector<fftw_iodim> howmany_dims(howmany_rank);
        for (intptr_t i = 0, j = 0, k = 0; i < howmany_rank; ++i, ++j) {
            for (; k < rank && j == axes(k).as<intptr_t>(); ++j, ++k) {
            }
            howmany_dims[i].n = shape.is_missing() ? src_size_stride[j].dim_size : shape(j).as<intptr_t>();
            howmany_dims[i].is = src_size_stride[j].stride / sizeof(fftw_src_type);
            howmany_dims[i].os = dst_size_stride[j].stride / sizeof(fftw_dst_type);
        }

        nd::array src = nd::empty(src_tp[0]);
        nd::array dst = nd::empty(dst_tp);

        fftw_ck::make(ckb, kernreq, ckb_offset,
                      detail::fftw_plan_guru_dft(rank, dims.get(), howmany_rank, howmany_dims.get(),
                              reinterpret_cast<fftw_src_type *>(src.data()),
                              reinterpret_cast<fftw_dst_type *>(dst.data()), sign, flags));

        return ckb_offset;
    }
示例#30
0
ScanResult scanTau(TH2* responseMatrix, TH1* input, bool writeCanvas=true)
{
    const int N = 2000;
    const int NBINS = responseMatrix->GetNbinsX();
    
    double* tau = new double[N];
    double* pmean = new double[N];
    double pmean_min=1.0;
    double pmean_min_tau=0.0;
    double* pmax = new double[N];
    double pmax_min=1.0;
    double pmax_min_tau=0.0;

    double** rho_avg = new double*[NBINS];
    for (int i = 0; i < NBINS; ++i)
    {
        rho_avg[i]=new double[N];
    }
    
    TH2D error("errorMatrixTauScan","",NBINS,0,NBINS,NBINS,0,NBINS);
    TUnfoldSys tunfold(responseMatrix,TUnfold::kHistMapOutputHoriz,TUnfold::kRegModeCurvature);
    for (int iscan=0;iscan< N;++iscan) 
    {
        tau[iscan]=TMath::Power(10.0,1.0*(iscan/(1.0*N)*5.0-7.0));
        tunfold.DoUnfold(tau[iscan],input);
        error.Scale(0.0);
        tunfold.GetEmatrix(&error);
        
        TMatrixD cov_matrix = convertHistToMatrix(error);
        TMatrixD inv_cov_matrix=TMatrixD(TMatrixD::kInverted,cov_matrix);
        TMatrixD diag_cov_halfs(NBINS,NBINS);
        for (int i=0; i<NBINS; ++i) {
            for (int j=0; j<NBINS; ++j) {
                if (i==j)
                {
                    diag_cov_halfs[i][j]=1.0/TMath::Sqrt((cov_matrix)[i][j]);
                }
                else
                {
                    diag_cov_halfs[i][j]=0.0;
                }
            }
        }
        //correlations of the unfolded dist
        TMatrixD rho = diag_cov_halfs*(cov_matrix)*diag_cov_halfs;
        
        //calculate the average per bin correlation; will be used in the "subway" plot
        for (int offrow = 1; offrow<NBINS; ++offrow)
        {
            double sum=0.0;
            for (int entry = 0; entry < NBINS-offrow; ++entry)
            {
                sum+=rho[offrow+entry][entry];
            }
            rho_avg[offrow][iscan]=sum/(NBINS-offrow);
        }
       
        double* p = new double[NBINS];
        pmean[iscan]=0.0; //will store the average global correlation over bins
        pmax[iscan]=0.0; //will store the max global correlation over bins
        for (int i=0; i<NBINS; ++i) 
        {
            //calculate the global correlations
            p[i]=sqrt(1.0-1.0/(inv_cov_matrix[i][i]*(cov_matrix)[i][i]));
            pmean[iscan]+=p[i];
            if (p[i]>pmax[iscan]) 
            {
                pmax[iscan]=p[i];
            }
        }
        pmean[iscan]=pmean[iscan]/(1.0*NBINS);
        
        //check if this is the minimum
        if (pmean[iscan]<pmean_min) 
        {
            pmean_min=pmean[iscan];
            pmean_min_tau=tau[iscan];
        }
        //check if this is the minimum
        if (pmax[iscan]<pmax_min) 
        {
            pmax_min=pmax[iscan];
            pmax_min_tau=tau[iscan];
        }
    }
    TCanvas cv_subway("cv_subway","",800,600);
    cv_subway.SetRightMargin(0.27);
    TH2F axes("axes",";#tau;#rho",50,tau[0],tau[N-1],50,-1.1,1.1);
    axes.Draw("AXIS");
    cv_subway.SetLogx(1);
    
    double Red[5]   = {0.00, 0.00, 0.83, 0.90, 0.65};
    double Green[5] = { 0.00, 0.71, 0.90, 0.15, 0.00};
    double Blue[5]   ={  0.71, 1.00, 0.12, 0.00, 0.00};
    double Length[5] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
    int start = TColor::CreateGradientColorTable(5,Length,Red,Green,Blue,(NBINS)*2);

    TLegend legend(0.74,0.9,0.99,0.2);
    legend.SetFillColor(kWhite);
    legend.SetBorderSize(0);
    legend.SetTextFont(42);
    
    for (int i=1; i<NBINS; ++i) 
    {
       
        TGraph* graph = new TGraph(N,tau,rho_avg[i]);
        graph->SetLineColor(start+(i-1)*2+1);
        graph->SetLineWidth(2);
        graph->Draw("SameL"); 
        
        char* graphName= new char[50];
        sprintf(graphName,"#LT #rho(i,i+%i) #GT",i);
        legend.AddEntry(graph,graphName,"L");
    }
    legend.AddEntry("","","");
    TGraph* graph_globalrho_avg = new TGraph(N,tau,pmean);
    graph_globalrho_avg->SetLineColor(kBlack);
    graph_globalrho_avg->SetLineStyle(2);
    graph_globalrho_avg->SetLineWidth(3);
    graph_globalrho_avg->Draw("SameL"); 
    legend.AddEntry(graph_globalrho_avg,"avg. global #rho","L");
    
    char* globalrho_mean= new char[50];
    sprintf(globalrho_mean,"#rho|min=%4.3f",pmean_min);
    legend.AddEntry("",globalrho_mean,"");
    char* globalrho_mean_tau= new char[50];
    sprintf(globalrho_mean_tau,"#tau|min=%3.2e",pmean_min_tau);
    legend.AddEntry("",globalrho_mean_tau,"");
    
    
    legend.AddEntry("","","");
    TGraph* graph_globalrho_max = new TGraph(N,tau,pmax);
    graph_globalrho_max->SetLineColor(kBlack);
    graph_globalrho_max->SetLineWidth(3);
    graph_globalrho_max->SetLineStyle(3);
    graph_globalrho_max->Draw("SameL"); 
    legend.AddEntry(graph_globalrho_max,"max. global #rho","L");
    
    char* globalrho_max= new char[50];
    sprintf(globalrho_max,"#rho|min=%4.3f",pmax_min);
    legend.AddEntry("",globalrho_max,"");
    char* globalrho_max_tau= new char[50];
    sprintf(globalrho_max_tau,"#tau|min=%3.2e",pmax_min_tau);
    legend.AddEntry("",globalrho_max_tau,"");
    
    legend.Draw("Same");
    if (writeCanvas)
    {
        cv_subway.Write();
    }
    ScanResult scanResult;
    scanResult.taumean=pmean_min_tau;
    scanResult.pmean=pmean_min;
    scanResult.taumax=pmax_min_tau;
    scanResult.pmax=pmax_min;
    return scanResult;
}