Esempio n. 1
0
/*!
  Returns the point at which the \a line intersects this box.
  The result is returned as a QResult<QVector3D> instance.

  When the line intersects the box at least once, a QResult<QVector3D>
  instance is returned where QResult::isValid() returns true; and
  where QResult::value() returns a QVector3D containing the intersection
  point.

  In the case where the origin point of the line lies on one of the box
  faces, this point is simply returned (with no floating point operations).

  The line might intersect at two points - as the line passes through
  the box - one on the near side, one on the far side; where near and far
  are relative to the origin point of the line.  This function only
  returns the near intersection point.

  Only positive values on the line are considered, that is if
  \c{qreal t == line.point(intersectionPoint)} then \bold t is positive.

  This means that if the origin point of the line is inside the box, there
  is only one solution, not two.  To get the other solution, simply change
  the sign of the lines direction vector.

  When the line does not intersect the box, the result returned will have
  a QResult::isValid() value of false.  In the case of an infinite box
  the result reflects that with QResult::OutOfRange
 */
QResult<QVector3D> QBox3D::intersection(const QLine3D &line) const
{
    if (boxtype == Null)
        return QResult<QVector3D>();
    if (boxtype == Infinite)
        return QResult<QVector3D>(QResult<QVector3D>::OutOfRange);

    QVector3D org = line.origin();
    Partition xpos, ypos, zpos;
    partition(org, &xpos, &ypos, &zpos);
    // if the lines origin lies on one of the faces, return it as the intersection
    if ((xpos | ypos | zpos) == (equalMin | equalMax))
        return org;

    // Could use the line/plane intersection functions, with 6 box planes defined by
    // 3 normals at the min and 3 at the max.  But since the planes are axis-aligned
    // there is a cheap optimization.  If the line P + tV intersects a AA-plane with
    // x = c at intersection point X, then P.x + tV.x = X.x = c; and therefore
    // t = (c - P.x) / V.x.  Here the value t is the scalar distance along V from P and
    // so it measures the value of the solution - see trackIntersection() above.
    qreal closest_t = 0.0f;
    QVector3D ln = line.direction();
    QVector3D closest_p;
    for (const QVector3D *p = &maxcorner; p; p = (p == &maxcorner) ? &mincorner : 0)
    {
        if (!qIsNull(ln.x()))
            trackIntersection(p->x() - org.x() / ln.x(), &closest_t, &closest_p, *this, line);
        if (!qIsNull(ln.y()))
            trackIntersection(p->y() - org.y() / ln.y(), &closest_t, &closest_p, *this, line);
        if (!qIsNull(ln.z()))
            trackIntersection(p->z() - org.z() / ln.z(), &closest_t, &closest_p, *this, line);
    }
    return closest_p;
}
Esempio n. 2
0
bool QTDSResult::gotoNext(QSqlCachedResult::ValueCache &values, int index)
{
    STATUS stat = dbnextrow(d->dbproc);
    if (stat == NO_MORE_ROWS) {
        setAt(QSql::AfterLastRow);
        return false;
    }
    if ((stat == FAIL) || (stat == BUF_FULL)) {
        setLastError(d->lastError);
        return false;
    }

    if (index < 0)
        return true;

    for (int i = 0; i < d->rec.count(); ++i) {
        int idx = index + i;
        switch (d->rec.field(i).type()) {
            case QVariant::DateTime:
                if (qIsNull(d->buffer.at(i * 2 + 1))) {
                    values[idx] = QVariant(QVariant::DateTime);
                } else {
                    DBDATETIME *bdt = (DBDATETIME*) d->buffer.at(i * 2);
                    QDate date = QDate::fromString(QLatin1String("1900-01-01"), Qt::ISODate);
                    QTime time = QTime::fromString(QLatin1String("00:00:00"), Qt::ISODate);
                    values[idx] = QDateTime(date.addDays(bdt->dtdays), time.addMSecs(int(bdt->dttime / 0.3)));
                }
                break;
            case QVariant::Int:
                if (qIsNull(d->buffer.at(i * 2 + 1)))
                    values[idx] = QVariant(QVariant::Int);
                else
                    values[idx] = *((int*)d->buffer.at(i * 2));
                break;
            case QVariant::Double:
            case QVariant::String:
                if (qIsNull(d->buffer.at(i * 2 + 1)))
                    values[idx] = QVariant(QVariant::String);
                else
                    values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2)).trimmed();
                break;
            case QVariant::ByteArray: {
                if (qIsNull(d->buffer.at(i * 2 + 1)))
                    values[idx] = QVariant(QVariant::ByteArray);
                else
                    values[idx] = QByteArray((const char*)d->buffer.at(i * 2));
                break;
            }
            default:
                // should never happen, and we already fired
                // a warning while binding.
                values[idx] = QVariant();
                break;
        }
    }

    return true;
}
void DrawPointTool::updateStatusText()
{
	if (isDragging())
	{
		auto angle = qRadiansToDegrees(preview_object->getRotation());
		setStatusBarText( trUtf8("<b>Angle:</b> %1° ").arg(QLocale().toString(angle, 'f', 1)) + QLatin1String("| ") +
		                  tr("<b>%1</b>: Fixed angles. ").arg(ModifierKey::control()) );
	}
	else if (static_cast<const PointSymbol*>(preview_object->getSymbol())->isRotatable())
	{
		auto parts = QStringList {
		    tr("<b>Click</b>: Create a point object."),
		    tr("<b>Drag</b>: Create an object and set its orientation."),
		};
		auto angle = qRadiansToDegrees(preview_object->getRotation());
		if (!qIsNull(angle))
		{
			parts.push_front(trUtf8("<b>Angle:</b> %1° ").arg(QLocale().toString(angle, 'f', 1)) + QLatin1Char('|'));
			parts.push_back(tr("<b>%1, 0</b>: Reset rotation.").arg(ModifierKey::escape()));
		}
		setStatusBarText(parts.join(QLatin1Char(' ')));
	}
	else
	{
		// Same as click_text above.
		setStatusBarText(tr("<b>Click</b>: Create a point object."));
	}
}
Esempio n. 4
0
TextRenderable::TextRenderable(const TextSymbol* symbol, const TextObject* text_object, const MapColor* color, double anchor_x, double anchor_y)
: Renderable { color }
, anchor_x   { anchor_x }
, anchor_y   { anchor_y }
, rotation   { 0.0 }
, scale_factor { symbol->getFontSize() / TextSymbol::internal_point_size }
{
	path.setFillRule(Qt::WindingFill);	// Otherwise, when text and an underline intersect, holes appear
	
	const QFont& font(symbol->getQFont());
	const QFontMetricsF& metrics(symbol->getFontMetrics());
	
	int num_lines = text_object->getNumLines();
	for (int i=0; i < num_lines; i++)
	{
		const TextObjectLineInfo* line_info = text_object->getLineInfo(i);
		
		double line_y = line_info->line_y;
		
		double underline_x0 = 0.0;
		double underline_y0 = line_info->line_y + metrics.underlinePos();
		double underline_y1 = underline_y0 + metrics.lineWidth();
		
		auto num_parts = line_info->part_infos.size();
		for (size_t j=0; j < num_parts; j++)
		{
			const TextObjectPartInfo& part(line_info->part_infos.at(j));
			if (font.underline())
			{
				if (j > 0)
				{
					// draw underline for gap between parts as rectangle
					// TODO: watch out for inconsistency between text and gap underline
					path.moveTo(underline_x0, underline_y0);
					path.lineTo(part.part_x,  underline_y0);
					path.lineTo(part.part_x,  underline_y1);
					path.lineTo(underline_x0, underline_y1);
					path.closeSubpath();
				}
				underline_x0 = part.part_x;
			}
			path.addText(part.part_x, line_y, font, part.part_text);
		}
	}
	
	QTransform t { 1.0, 0.0, 0.0, 1.0, anchor_x, anchor_y };
	t.scale(scale_factor, scale_factor);
	
	auto rotation_rad = text_object->getRotation();
	if (!qIsNull(rotation_rad))
	{
		rotation = -qRadiansToDegrees(rotation_rad);
		t.rotate(rotation);
	}
	
	extent = t.mapRect(path.controlPointRect());
}
Esempio n. 5
0
Scratch::Scratch(qreal minLife, qreal maxLife,
                 qreal minDLife, qreal maxDLife,
                 qreal minX, qreal maxX,
                 qreal minDX, qreal maxDX,
                 int minY, int maxY)
{
    this->m_life = this->m_life0 = qrand() * (maxLife - minLife) / RAND_MAX + minLife;
    this->m_dlife = qrand() * (maxDLife - minDLife) / RAND_MAX + minDLife;

    if (!qIsNull(this->m_dlife))
        this->m_dlife = maxDLife - minDLife;

    this->m_x = qrand() * (maxX - minX) / RAND_MAX + minX;
    this->m_dx = qrand() * (maxDX - minDX) / RAND_MAX + minDX;

    if (!qIsNull(this->m_dx))
        this->m_dx = maxDX - minDX;

//    this->m_dx *= (qrand() & 0x1? 1.0: -1.0);

    this->m_y = int(qrand() * (maxY - minY) / RAND_MAX) + minY;
}
Esempio n. 6
0
/*!
  \internal
  Use a kind of cheap hill-climbing approach to find the point intersection,
  where the heuristic is the value of t, the scalar representing the distance
  from the line's origin point to the intersection under consideration.  If
  the t for the intersection being considered is less than t's for other
  intersections then it might be a solution, in which case do the calculation
  to find the point Q = P + tV on the line.  Once the point is found, test it
  to see if it really is a solution (lies in the box) before updating the
  heuristic.
 */
inline static void trackIntersection(qreal t, qreal *closest_t, QVector3D *closest_p,
                         const QBox3D &box, const QLine3D &line)
{
    if ((t > 0.0f && t < *closest_t) || qIsNull(*closest_t))
    {
        // only consider non-negative values of t, and ones better than best
        // value found so far
        QVector3D p = line.point(t);
        if (box.contains(p))
        {
            *closest_p = p;
            *closest_t = t;
        }
    }
}
Esempio n. 7
0
void MyLineEdit::wheelEvent(QWheelEvent *event)
{
	if (slider) // if it's edit field with slider (not text)
	{
		double value = systemData.locale.toDouble(text());

		double change = event->delta() / 360.0;

		if (qIsNull(value)) value = (change > 0.0) ? 0.1 : -0.1;

		if (value < 0.0) change *= -1.0;

		double multiplier = (1.0 + change / 10.0);

		const QString text = QString("%L1").arg(value * multiplier, 0, 'g', 16);
		setText(text);
		emit returnPressed();
		event->accept();
	}
}
bool QmlAnchors::instanceHasMargin(AnchorLine::Type sourceAnchorLineType) const
{
    return !qIsNull(instanceMargin(sourceAnchorLineType));
}
Esempio n. 9
0
// Fix the problem where a compared value happens to be zero (and
// you cannot always predict this, and should not predict it
// since then you produce self-fulling prophecies instead of tests).
// In that case qFuzzyCompare has a completely strict criterion since
// it finds the "fudge factor" by multiplying by zero...
static inline bool fuzzyCompare(float p1, float p2)
{
    float fac = qMin(qAbs(p1), qAbs(p2));
    return (qAbs(p1 - p2) <= (qIsNull(fac) ? 0.00001f : 0.00001f * fac));
}
Esempio n. 10
0
/*!
    Returns the 3D vector form of this 4D vector, dividing the x, y, and
    z coordinates by the w coordinate.  Returns a null vector if w is zero.

    \sa toVector3D(), toVector2DAffine(), toPoint()
*/
QVector3D QVector4D::toVector3DAffine() const
{
    if (qIsNull(wp))
        return QVector3D();
    return QVector3D(xp / wp, yp / wp, zp / wp);
}
Esempio n. 11
0
/*!
    Returns the 2D vector form of this 4D vector, dividing the x and y
    coordinates by the w coordinate and dropping the z coordinate.
    Returns a null vector if w is zero.

    \sa toVector2D(), toVector3DAffine(), toPoint()
*/
QVector2D QVector4D::toVector2DAffine() const
{
    if (qIsNull(wp))
        return QVector2D();
    return QVector2D(xp / wp, yp / wp, 1);
}