Beispiel #1
0
QPolygonF QwtSpline::polygonP( const QPolygonF &points, 
    double delta, bool withNodes ) const
{
    if ( delta <= 0.0 )
        return QPolygonF();

    const int n = points.size();
    if ( n <= 1 )
        return points;

    if ( n == 2 )
    {
        // TODO
        return points;
    }

    QPolygonF path;

    const QVector<QLineF> controlPoints = bezierControlPointsP( points );

    if ( controlPoints.size() < n - 1 )
        return path;

    path += points.first();
    double t = delta;

    for ( int i = 0; i < n - 1; i++ )
    {
#if 1
        const double l = d_parameter->value( points[i], points[i+1] );
#endif

        while ( t < l )
        {
            path += qwtBezierPoint( points[i], controlPoints[i].p1(),
                controlPoints[i].p2(), points[i+1], t / l );

            t += delta;
        }

        if ( withNodes )
        {
            if ( qFuzzyCompare( path.last().x(), points[i+1].x() ) )
                path.last() = points[i+1];
            else
                path += points[i+1];

            t = delta;
        }
        else
        {
            t -= l;
        }
    }

    if ( controlPoints.size() >= n )
    {
        const double l = d_parameter->value( points[n-1], points[0] );

        while ( t < l )
        {
            path += qwtBezierPoint( points[n-1], controlPoints[n-1].p1(),
                controlPoints[n-1].p2(), points[0], t / l );

            t += delta;
        }

        if ( qFuzzyCompare( path.last().x(), points[0].x() ) )
            path.last() = points[0];
        else 
            path += points[0];
    }

    return path;
}
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement )
{
  if ( points.isEmpty() )
    return;

  QgsRenderContext& rc = context.renderContext();

  double origAngle = mMarker->angle();
  double angle;
  int i, maxCount;
  bool isRing = false;

  if ( placement == FirstVertex )
  {
    i = 0;
    maxCount = 1;
  }
  else if ( placement == LastVertex )
  {
    i = points.count() - 1;
    maxCount = points.count();
  }
  else
  {
    i = 0;
    maxCount = points.count();
    if ( points.first() == points.last() )
      isRing = true;
  }

  for ( ; i < maxCount; ++i )
  {
    const QPointF& pt = points[i];

    // rotate marker (if desired)
    if ( mRotateMarker )
    {
      if ( i == 0 )
      {
        if ( !isRing )
        {
          // use first segment's angle
          const QPointF& nextPt = points[i+1];
          if ( pt == nextPt )
            continue;
          angle = MyLine( pt, nextPt ).angle();
        }
        else
        {
          // closed ring: use average angle between first and last segment
          const QPointF& prevPt = points[points.count() - 2];
          const QPointF& nextPt = points[1];
          if ( prevPt == pt || nextPt == pt )
            continue;

          angle = _averageAngle( prevPt, pt, nextPt );
        }
      }
      else if ( i == points.count() - 1 )
      {
        if ( !isRing )
        {
          // use last segment's angle
          const QPointF& prevPt = points[i-1];
          if ( pt == prevPt )
            continue;
          angle = MyLine( prevPt, pt ).angle();
        }
        else
        {
          // don't draw the last marker - it has been drawn already
          continue;
        }
      }
      else
      {
        // use average angle
        const QPointF& prevPt = points[i-1];
        const QPointF& nextPt = points[i+1];
        if ( prevPt == pt || nextPt == pt )
          continue;

        angle = _averageAngle( prevPt, pt, nextPt );
      }
      mMarker->setAngle( origAngle + angle * 180 / M_PI );
    }

    mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
  }

  // restore original rotation
  mMarker->setAngle( origAngle );
}
Beispiel #3
0
void CreateObjectTool::mouseMoved(const QPointF &pos,
                                  Qt::KeyboardModifiers modifiers)
{
    AbstractObjectTool::mouseMoved(pos, modifiers);

    if (!mNewMapObjectItem)
        return;

    const MapRenderer *renderer = mapDocument()->renderer();

    bool snapToGrid = Preferences::instance()->snapToGrid();
    if (modifiers & Qt::ControlModifier)
        snapToGrid = !snapToGrid;

    switch (mMode) {
    case CreateRectangle:
    case CreateEllipse: {
        const QPointF tileCoords = renderer->pixelToTileCoords(pos);

        // Update the size of the new map object
        const QPointF objectPos = mNewMapObjectItem->mapObject()->position();
        QSizeF newSize(qMax(qreal(0), tileCoords.x() - objectPos.x()),
                       qMax(qreal(0), tileCoords.y() - objectPos.y()));

        if (snapToGrid)
            newSize = newSize.toSize();

        // Holding shift creates circle or square
        if (modifiers & Qt::ShiftModifier) {
            qreal max = qMax(newSize.width(), newSize.height());
            newSize.setWidth(max);
            newSize.setHeight(max);
        }

        mNewMapObjectItem->resize(newSize);
        break;
    }
    case CreateTile: {
        const QSize imgSize = mNewMapObjectItem->mapObject()->tile()->size();
        const QPointF diff(-imgSize.width() / 2, imgSize.height() / 2);
        QPointF tileCoords = renderer->pixelToTileCoords(pos + diff);

        if (snapToGrid)
            tileCoords = tileCoords.toPoint();

        mNewMapObjectItem->mapObject()->setPosition(tileCoords);
        mNewMapObjectItem->syncWithMapObject();
        break;
    }
    case CreatePolygon:
    case CreatePolyline: {
        QPointF tileCoords = renderer->pixelToTileCoords(pos);

        if (snapToGrid)
            tileCoords = tileCoords.toPoint();

        tileCoords -= mNewMapObjectItem->mapObject()->position();

        QPolygonF polygon = mOverlayPolygonObject->polygon();
        polygon.last() = tileCoords;
        mOverlayPolygonItem->setPolygon(polygon);
        break;
    }
    }
}
Beispiel #4
0
void CreateObjectTool::mousePressed(QGraphicsSceneMouseEvent *event)
{
    // Check if we are already creating a new map object
    if (mNewMapObjectItem) {
        switch (mMode) {
        case CreateRectangle:
        case CreateTile:
        case CreateEllipse:
            if (event->button() == Qt::RightButton)
                cancelNewMapObject();
            break;
        case CreatePolygon:
        case CreatePolyline:
            if (event->button() == Qt::RightButton) {
                // The polygon needs to have at least three points and a
                // polyline needs at least two.
                int min = mMode == CreatePolygon ? 3 : 2;
                if (mNewMapObjectItem->mapObject()->polygon().size() >= min)
                    finishNewMapObject();
                else
                    cancelNewMapObject();
            } else if (event->button() == Qt::LeftButton) {
                QPolygonF current = mNewMapObjectItem->mapObject()->polygon();
                QPolygonF next = mOverlayPolygonObject->polygon();

                // If the last position is still the same, ignore the click
                if (next.last() == current.last())
                    return;

                // Assign current overlay polygon to the new object
                mNewMapObjectItem->setPolygon(next);

                // Add a new editable point to the overlay
                next.append(next.last());
                mOverlayPolygonItem->setPolygon(next);
            }
            break;
        }
        return;
    }

    if (event->button() != Qt::LeftButton) {
        AbstractObjectTool::mousePressed(event);
        return;
    }

    ObjectGroup *objectGroup = currentObjectGroup();
    if (!objectGroup || !objectGroup->isVisible())
        return;

    const MapRenderer *renderer = mapDocument()->renderer();
    QPointF tileCoords;

    if (mMode == CreateTile) {
        if (!mTile)
            return;

        const QPointF diff(-mTile->width() / 2, mTile->height() / 2);
        tileCoords = renderer->pixelToTileCoords(event->scenePos() + diff);
    } else {
        tileCoords = renderer->pixelToTileCoords(event->scenePos());
    }

    bool snapToGrid = Preferences::instance()->snapToGrid();
    if (event->modifiers() & Qt::ControlModifier)
        snapToGrid = !snapToGrid;

    if (snapToGrid)
        tileCoords = tileCoords.toPoint();

    startNewMapObject(tileCoords, objectGroup);
}
Beispiel #5
0
void MaGraphOverview::drawOverview(QPainter &p) {
    if (displaySettings->orientation == MaGraphOverviewDisplaySettings::FromTopToBottom) {
        // transform coordinate system
        p.translate( 0, height());
        p.scale(1, -1);
    }

    p.fillRect(cachedConsensus.rect(), Qt::white);

    if (editor->getAlignmentLen() == 0) {
        return;
    }

    p.setPen(displaySettings->color);
    p.setBrush(displaySettings->color);

    if (graphCalculationTaskRunner.getResult().isEmpty() && !editor->isAlignmentEmpty() && !isBlocked) {
        sl_drawGraph();
        return;
    }

    QPolygonF resultPolygon = graphCalculationTaskRunner.getResult();
    if (!editor->isAlignmentEmpty() && resultPolygon.last().x() != width()) {
        sl_drawGraph();
        return;
    }

    // area graph
    if (displaySettings->type == MaGraphOverviewDisplaySettings::Area) {
        p.drawPolygon( resultPolygon );
    }

    // line graph
    if (displaySettings->type == MaGraphOverviewDisplaySettings::Line) {
        p.drawPolyline( resultPolygon );
    }

    // hystogram
    if (displaySettings->type == MaGraphOverviewDisplaySettings::Hystogram) {
        int size = graphCalculationTaskRunner.getResult().size();
        for (int i = 0; i < size; i++) {
            const QPointF point = resultPolygon.at(i);
            QPointF nextPoint;
            if (i != size - 1) {
                nextPoint = resultPolygon.at(i + 1);
            } else {
                nextPoint = QPointF(width(), point.y());
            }

            p.drawRect( point.x(), point.y(),
                        static_cast<int>(nextPoint.x() - point.x()) - 2 * (width() > 2 * size),
                        height() - point.y());
        }
    }

    // gray frame
    p.setPen(Qt::gray);
    p.setBrush(Qt::transparent);
    p.drawRect( rect().adjusted( 0, (displaySettings->orientation == MaGraphOverviewDisplaySettings::FromTopToBottom),
                                 -1, -1 * (displaySettings->orientation == MaGraphOverviewDisplaySettings::FromBottomToTop)));

}
Beispiel #6
0
void ClipPainterPrivate::clipPolyObject ( const QPolygonF & polygon, 
                                          QVector<QPolygonF> & clippedPolyObjects,
                                          bool isClosed )
{
    //	mDebug() << "ClipPainter enabled." ;

    // Only create a new polyObject as soon as we know for sure that 
    // the current point is on the screen. 
    QPolygonF clippedPolyObject = QPolygonF();

    const QVector<QPointF>::const_iterator  itStartPoint = polygon.constBegin();
    const QVector<QPointF>::const_iterator  itEndPoint   = polygon.constEnd();
    QVector<QPointF>::const_iterator        itPoint      = itStartPoint;

    // We use a while loop to be able to cover linestrings as well as linear rings:
    // Linear rings require to tessellate the path from the last node to the first node
    // which isn't really convenient to achieve with a for loop ...

    bool processingLastNode = false;

    while ( itPoint != itEndPoint ) {
        m_currentPoint = (*itPoint);
        // mDebug() << "m_currentPoint.x()" << m_currentPoint.x() << "m_currentPOint.y()" << m_currentPoint.y();

        // Figure out the sector of the current point.
        m_currentSector = sector( m_currentPoint );

        // Initialize the variables related to the previous point.
        if ( itPoint == itStartPoint && processingLastNode == false ) {
            if ( isClosed ) {
                m_previousPoint = polygon.last();

                // Figure out the sector of the previous point.
                m_previousSector = sector( m_previousPoint );
            }
            else {
                m_previousSector = m_currentSector;
            }
        }

        // If the current point reaches a new sector, take care of clipping.
        if ( m_currentSector != m_previousSector ) {
            if ( m_currentSector == 4 || m_previousSector == 4 ) {
                // In this case the current or the previous point is visible on the
                // screen but not both. Hence we only need to clip once and require
                // only one interpolation for both cases.

                clipOnce( clippedPolyObject, clippedPolyObjects, isClosed );
            }
            else {
                // This case mostly deals with lines that reach from one
                // sector that is located off screen to another one that
                // is located off screen. In this situation the line 
                // can get clipped once, twice, or not at all.
                clipMultiple( clippedPolyObject, clippedPolyObjects, isClosed );
            }

            m_previousSector = m_currentSector;
        }

        // If the current point is onscreen, just add it to our final polygon.
        if ( m_currentSector == 4 ) {

            clippedPolyObject << m_currentPoint;
#ifdef MARBLE_DEBUG
            ++(m_debugNodeCount);
#endif
        }

        m_previousPoint = m_currentPoint;

        // Now let's handle the case where we have a (closed) polygon and where the
        // last point of the polyline is outside the viewport and the start point
        // is inside the viewport. This needs special treatment
        if ( processingLastNode ) {
            break;
        }
        ++itPoint;

        if ( itPoint == itEndPoint  && isClosed ) {
            itPoint = itStartPoint;
            processingLastNode = true;
        }
    }

    // Only add the pointer if there's node data available.
    if ( !clippedPolyObject.isEmpty() ) {
        clippedPolyObjects << clippedPolyObject;
    }
}
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement )
{
  if ( points.isEmpty() )
    return;

  QgsRenderContext& rc = context.renderContext();

  double origAngle = mMarker->angle();
  int i, maxCount;
  bool isRing = false;

  double offsetAlongLine = mOffsetAlongLine;
  QgsExpression* offsetAlongLineExpression = expression( "offset_along_line" );
  if ( offsetAlongLineExpression )
  {
    offsetAlongLine = offsetAlongLineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
  }
  if ( offsetAlongLine != 0 )
  {
    //scale offset along line
    offsetAlongLine *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale );
  }

  if ( placement == FirstVertex )
  {
    i = 0;
    maxCount = 1;
  }
  else if ( placement == LastVertex )
  {
    i = points.count() - 1;
    maxCount = points.count();
  }
  else
  {
    i = 0;
    maxCount = points.count();
    if ( points.first() == points.last() )
      isRing = true;
  }

  if ( offsetAlongLine > 0 && ( placement == FirstVertex || placement == LastVertex ) )
  {
    double distance;
    distance = placement == FirstVertex ? offsetAlongLine : -offsetAlongLine;
    renderOffsetVertexAlongLine( points, i, distance, context );
    // restore original rotation
    mMarker->setAngle( origAngle );
    return;
  }

  for ( ; i < maxCount; ++i )
  {
    if ( isRing && placement == Vertex && i == points.count() - 1 )
    {
      continue; // don't draw the last marker - it has been drawn already
    }
    // rotate marker (if desired)
    if ( mRotateMarker )
    {
      double angle = markerAngle( points, isRing, i );
      mMarker->setAngle( origAngle + angle * 180 / M_PI );
    }

    mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
  }

  // restore original rotation
  mMarker->setAngle( origAngle );
}
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement )
{
  if ( points.isEmpty() )
    return;

  QgsRenderContext& rc = context.renderContext();

  double origAngle = mMarker->angle();
  int i, maxCount;
  bool isRing = false;

  double offsetAlongLine = mOffsetAlongLine;
  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE ) )
  {
    context.setOriginalValueVariable( mOffsetAlongLine );
    offsetAlongLine = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE, context, mOffsetAlongLine ).toDouble();
  }
  if ( offsetAlongLine != 0 )
  {
    //scale offset along line
    offsetAlongLine = QgsSymbolLayerV2Utils::convertToPainterUnits( rc, offsetAlongLine, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale );
  }

  if ( offsetAlongLine == 0 && context.renderContext().geometry()
       && context.renderContext().geometry()->hasCurvedSegments() && ( placement == Vertex || placement == CurvePoint ) )
  {
    const QgsCoordinateTransform* ct = context.renderContext().coordinateTransform();
    const QgsMapToPixel& mtp = context.renderContext().mapToPixel();

    QgsVertexId vId;
    QgsPointV2 vPoint;
    double x, y, z;
    QPointF mapPoint;
    while ( context.renderContext().geometry()->nextVertex( vId, vPoint ) )
    {
      if (( placement == Vertex && vId.type == QgsVertexId::SegmentVertex )
          || ( placement == CurvePoint && vId.type == QgsVertexId::CurveVertex ) )
      {
        //transform
        x = vPoint.x(), y = vPoint.y(); z = vPoint.z();
        if ( ct )
        {
          ct->transformInPlace( x, y, z );
        }
        mapPoint.setX( x ); mapPoint.setY( y );
        mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
        if ( mRotateMarker )
        {
          double angle = context.renderContext().geometry()->vertexAngle( vId );
          mMarker->setAngle( angle * 180 / M_PI );
        }
        mMarker->renderPoint( mapPoint, context.feature(), rc, -1, context.selected() );
      }
    }
    return;
  }

  if ( placement == FirstVertex )
  {
    i = 0;
    maxCount = 1;
  }
  else if ( placement == LastVertex )
  {
    i = points.count() - 1;
    maxCount = points.count();
  }
  else if ( placement == Vertex )
  {
    i = 0;
    maxCount = points.count();
    if ( points.first() == points.last() )
      isRing = true;
  }
  else
  {
    return;
  }

  if ( offsetAlongLine > 0 && ( placement == FirstVertex || placement == LastVertex ) )
  {
    double distance;
    distance = placement == FirstVertex ? offsetAlongLine : -offsetAlongLine;
    renderOffsetVertexAlongLine( points, i, distance, context );
    // restore original rotation
    mMarker->setAngle( origAngle );
    return;
  }

  for ( ; i < maxCount; ++i )
  {
    if ( isRing && placement == Vertex && i == points.count() - 1 )
    {
      continue; // don't draw the last marker - it has been drawn already
    }
    // rotate marker (if desired)
    if ( mRotateMarker )
    {
      double angle = markerAngle( points, isRing, i );
      mMarker->setAngle( origAngle + angle * 180 / M_PI );
    }

    mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
  }

  // restore original rotation
  mMarker->setAngle( origAngle );
}
Beispiel #9
0
bool DataConverter::digitalPattern_Rotate(QPolygonF &points, qreal angle)
{
	if (angle == 0.0)
		return true;

	if (angle < -180.0 || angle > 180.0)
	{
		qDebug("[DataConverter::digitalPattern_Rotate] Error: Angle: [%f]", angle);
		return false;
	}

	if (points.size() < 10)
	{
		qDebug("[DataConverter::digitalPattern_Rotate] Error: Polygon Point Count: [%d]", points.size());
		return false;
	}

	//
	QTransform transform;

	transform.rotate(angle);

	points = transform.map(points);

	//
	int bottomIndex = 0;

	{
		qreal tmpX = -9999.99;

		for (int i = 0; i < points.size(); i++)
		{
			if (points.at(i).y() < 0.0)
				continue;

			if (points.at(i).x() > 0.0)
				continue;

			if (points.at(i).x() > tmpX)
			{
				tmpX = points.at(i).x();
				bottomIndex = i;
			}
		}
	}

	qDebug("** bottomIndex: [%d]", bottomIndex);

	if (bottomIndex > 0)
	{
		QPointF tmpPoint;

		for (int i = points.size() - 1; i >= bottomIndex; i--)
		{
			tmpPoint = points.last();
			points.pop_back();
			points.push_front(tmpPoint);
		}
	}

	return true;
}
Beispiel #10
0
void CreateObjectTool::mouseMoved(const QPointF &pos,
                                  Qt::KeyboardModifiers modifiers)
{
    AbstractObjectTool::mouseMoved(pos, modifiers);

    if (!mNewMapObjectItem)
        return;

    const MapRenderer *renderer = mapDocument()->renderer();

    bool snapToGrid = Preferences::instance()->snapToGrid();
    bool snapToFineGrid = Preferences::instance()->snapToFineGrid();
    if (modifiers & Qt::ControlModifier) {
        snapToGrid = !snapToGrid;
        snapToFineGrid = false;
    }

    switch (mMode) {
    case CreateRectangle:
    case CreateEllipse: {
        const QPointF pixelCoords = renderer->screenToPixelCoords(pos);

        // Update the size of the new map object
        const QPointF objectPos = mNewMapObjectItem->mapObject()->position();
        QPointF newSize(qMax(qreal(0), pixelCoords.x() - objectPos.x()),
                        qMax(qreal(0), pixelCoords.y() - objectPos.y()));
        QPointF newTileSize = renderer->pixelToTileCoords(newSize);

        if (snapToFineGrid) {
            int gridFine = Preferences::instance()->gridFine();
            newTileSize = (newTileSize * gridFine).toPoint();
            newTileSize /= gridFine;
        } else if (snapToGrid)
            newTileSize = newTileSize.toPoint();

        // Holding shift creates circle or square
        if (modifiers & Qt::ShiftModifier) {
            qreal max = qMax(newTileSize.x(), newTileSize.y());
            newTileSize.setX(max);
            newTileSize.setY(max);
        }
        
        newSize = renderer->tileToPixelCoords(newTileSize);
        
        mNewMapObjectItem->resizeObject(QSizeF(newSize.x(), newSize.y()));
        break;
    }
    case CreateTile: {
        const QSize imgSize = mNewMapObjectItem->mapObject()->cell().tile->size();
        const QPointF diff(-imgSize.width() / 2, imgSize.height() / 2);
        QPointF tileCoords = renderer->screenToTileCoords(pos + diff);

        if (snapToFineGrid) {
            int gridFine = Preferences::instance()->gridFine();
            tileCoords = (tileCoords * gridFine).toPoint();
            tileCoords /= gridFine;
        } else if (snapToGrid)
            tileCoords = tileCoords.toPoint();
        
        QPointF pixelCoords = renderer->tileToPixelCoords(tileCoords);

        mNewMapObjectItem->mapObject()->setPosition(pixelCoords);
        mNewMapObjectItem->syncWithMapObject();
        mNewMapObjectItem->setZValue(10000); // sync may change it
        break;
    }
    case CreatePolygon:
    case CreatePolyline: {
        QPointF tileCoords = renderer->screenToTileCoords(pos);

        if (snapToFineGrid) {
            int gridFine = Preferences::instance()->gridFine();
            tileCoords = (tileCoords * gridFine).toPoint();
            tileCoords /= gridFine;
        } else if (snapToGrid)
            tileCoords = tileCoords.toPoint();
        
        QPointF pixelCoords = renderer->tileToPixelCoords(tileCoords);
        pixelCoords -= mNewMapObjectItem->mapObject()->position();

        QPolygonF polygon = mOverlayPolygonObject->polygon();
        polygon.last() = pixelCoords;
        mOverlayPolygonItem->setPolygon(polygon);
        break;
    }
    }
}
Beispiel #11
0
void _PolyClipper::clipPolyline(const QPolygonF& poly)
{
  // exit if fewer than 2 points in polygon
  if ( poly.size() < 2 )
    return;

  // output goes here
  QPolygonF pout;

  QPolygonF::const_iterator polyiter = poly.begin();
  QPointF lastpt = *polyiter;
  polyiter++;

  for( ; polyiter != poly.end(); ++polyiter )
    {
      QPointF p1 = lastpt;
      QPointF p2 = *polyiter;

      bool plotline = _clipper.clipLine(p1, p2);
      if( plotline )
        {
          if( pout.isEmpty() )
            {
              // add first line
              pout << p1;
              if( ! smallDelta(p1, p2) )
                pout << p2;
            }
          else
            {
              if( p1 == pout.last() )
                {
                  if( ! smallDelta(p1, p2) )
                    // extend polyline
                    pout << p2;
                }
              else
                {
                  // paint existing line
                  if( pout.size() >= 2 )
                    emitPolyline(pout);

                  // start new line
                  pout.clear();
                  pout << p1;
                  if( ! smallDelta(p1, p2) )
                    pout << p2;
                }
            }
        }
      else
        {
          // line isn't in region, so ignore results from clip function

          // paint existing line
          if( pout.size() >= 2 )
            emitPolyline(pout);

          // cleanup
          pout.clear();
        }


      lastpt = *polyiter;
    }

  if( pout.size() >= 2 )
    emitPolyline(pout);
}
Beispiel #12
0
void assertPolygonIsClosed(QPolygonF polygon)
{
  ASSERT_RETURN(polygon.isEmpty() || polygon.first() == polygon.last());
}
Beispiel #13
0
QPolygonF minigis::shiftPolygonSimple(const QPolygonF &origin, qreal delta, bool closed)
{
    QPolygonF path = origin;

    QPolygonF norm;
    // ----------------- Поиск нормалей к оригинальному полигону
    int N = path.size();
    for (int i = 1; i < N; ++i) {
        QPointF vect = path.at(i) - path.at(i-1);
        double len = lengthR2(vect);
        if (qFuzzyIsNull(len)) {
            path.remove(i);
            --N;
            --i;
            continue;
        }
        vect /= len;
        norm.append(QPointF(vect.y() * delta, -vect.x() * delta));
    }
    // ----
    if (closed) {
        QPointF vect = path.first() - path.last();
        double len = lengthR2(vect);
        if (qFuzzyIsNull(len))
            path.remove(path.size() - 1);
        else {
            vect /= len;
            norm.append(QPointF(vect.y() * delta, -vect.x() * delta));
        }
    }
    // ------------------

    QVector<QLineF> lines;
    // -------------------------- Построение смещенных линий
    for (int i = 1; i < path.size(); ++i)
        lines.append(QLineF(path.at(i) + norm.at(i-1), path.at(i-1) + norm.at(i-1)));
    // ----
    if (closed)
        lines.append(QLineF(path.first() + norm.last(), path.last() + norm.last()));
    // ------------------

    QPolygonF shell;
    if (lines.isEmpty())
        return shell;

    // -------------------------- Построение смещенного полигона
    N = lines.size();
    for (int i = 1; i < N; ++i) {
        QPointF tmp;
        QLineF::IntersectType type = lines.at(i-1).intersect(lines.at(i), &tmp);
        double ang = lines.at(i-1).angleTo(lines.at(i));
        if (type != QLineF::NoIntersection)
            shell.append(tmp);
        else {
            if (qFuzzyCompare(ang, 180.))
                shell.append(lines.at(i).p2() - 2 * norm.at(i));
            shell.append(lines.at(i).p2());
        }
    }
    // ----
    if (closed) {
        QPointF tmp;
        QLineF::IntersectType type = lines.last().intersect(lines.first(), &tmp);
        double ang = lines.last().angleTo(lines.first());
        if (type != QLineF::NoIntersection)
            shell.append(tmp);
        else {
            if (qFuzzyCompare(ang, 180.))
                shell.append(lines.first().p2() - 2 * norm.first());
            shell.append(lines.first().p2());
        }
        shell.append(shell.first());
    }
    else {
        shell.prepend(lines.first().p2());
        shell.append(lines.last().p1());
    }
    // ------------------

    return shell;
}
Beispiel #14
0
QPolygonF minigis::shiftPolygonDifficult(const QPolygonF &origin, qreal delta, bool closed)
{
    if (qFuzzyIsNull(delta))
        return origin;

    QPolygonF path = origin;

    QPolygonF norm;
    // ----------------- Поиск нормалей к оригинальному полигону
    int N = path.size();
    for (int i = 1; i < N; ++i) {
        QPointF vect = path.at(i) - path.at(i-1);
        double len = lengthR2(vect);
        if (qFuzzyIsNull(len)) {
            path.remove(i);
            --N;
            --i;
            continue;
        }
        vect /= len;
        norm.append(QPointF(vect.y() * delta, -vect.x() * delta));
    }
    // ----
    if (closed) {
        QPointF vect = path.first() - path.last();
        double len = lengthR2(vect);
        if (qFuzzyIsNull(len))
            path.remove(path.size() - 1);
        else {
            vect /= len;
            norm.append(QPointF(vect.y() * delta, -vect.x() * delta));
        }
    }
    // ------------------

    QVector<QLineF> lines;
    // -------------------------- Построение смещенных линий
    for (int i = 1; i < path.size(); ++i)
        lines.append(QLineF(path.at(i) + norm.at(i-1), path.at(i-1) + norm.at(i-1)));
    // ----
    if (closed)
        lines.append(QLineF(path.first() + norm.last(), path.last() + norm.last()));
    // ------------------

    QPolygonF shell;
    if (lines.isEmpty())
        return shell;

    // -------------------------- Построение смещенного полигона
    N = lines.size();
    for (int i = 1; i < N; ++i) {
        QPointF tmp;
        QLineF::IntersectType type = lines.at(i-1).intersect(lines.at(i), &tmp);
        qreal ang = lines.at(i-1).angleTo(lines.at(i));
        if (type != QLineF::NoIntersection)
            shell.append(tmp);
        else {
            if (qFuzzyCompare(ang, qreal(180)))
                shell.append(lines.at(i).p2() - 2 * norm.at(i));
            shell.append(lines.at(i).p2());
        }
    }
    // ----
    if (closed) {
        QPointF tmp;
        QLineF::IntersectType type = lines.last().intersect(lines.first(), &tmp);
        qreal ang = lines.last().angleTo(lines.first());
        if (type != QLineF::NoIntersection)
            shell.append(tmp);
        else {
            if (qFuzzyCompare(ang, qreal(180)))
                shell.append(lines.first().p2() - 2 * norm.first());
            shell.append(lines.first().p2());
        }
        shell.append(shell.first());
    }
    else {
        shell.prepend(lines.first().p2());
        shell.append(lines.last().p1());
    }
    // ------------------

    // -------------------------- обрезание острых углов
    int k  = 0;
    N = lines.size();
    for (int i = 1; i < N; ++i) {
        double ang = lines.at(i-1).angleTo(lines.at(i));

        bool first  = (120 < ang && ang < 180 && delta < 0) || (180 < ang && ang < 240 && delta > 0);
        bool second = (120 < ang && ang < 180 && delta > 0) || (180 < ang && ang < 240 && delta < 0);
        if (first) {
            int num = closed ? 1 : 0;
            QPointF v = shell.at(i + k - num) - path.at(i);
            v /= lengthR2(v);
            QPointF start = path.at(i) + v * qAbs(delta);
            QLineF tmp(start, start + QPointF(-v.y(), v.x()));
            QPointF a;
            if (tmp.intersect(lines.at(i  ), &a) != QLineF::NoIntersection)
                shell.replace(i + k - num, a);
            if (tmp.intersect(lines.at(i-1), &a) != QLineF::NoIntersection)
                shell.insert(i + k - num, a);
            ++k;
        }
        else if (second) {
            // TODO: cut corner
        }
    }
    // ----
    if (closed) {
        double ang = lines.last().angleTo(lines.first());

        int num = lines.size();
        int shellNum = (num + k - 1) % shell.size();
        bool first  = (120 < ang && ang < 180 && delta < 0) || (180 < ang && ang < 240 && delta > 0);
        bool second = (180 < ang && ang < 240 && delta < 0) || (120 < ang && ang < 180 && delta > 0);
        if (first) {
            QPointF v = shell.at(shellNum) - path.at(num % path.size());
            v /= lengthR2(v);
            QPointF start = path.at(num % path.size()) + v * qAbs(delta);
            QLineF tmp(start, start + QPointF(-v.y(), v.x()));
            QPointF a;
            if (tmp.intersect(lines.first(), &a) != QLineF::NoIntersection)
                shell.replace(shellNum, a);
            if (tmp.intersect(lines.last() , &a) != QLineF::NoIntersection)
                shell.insert(shellNum, a);
        }
        else if (second) {
            // TODO: cut corner
        }
    }
    // ------------------

    return shell;
}
Beispiel #15
0
/**
 * Try to reduce the point size of a polyline.
 *
 * \param range Corridor beside the course line in meters.
 *
 * \param mwList list of polylines to be processed.
 *
 * \return list with reduced polylines.
 */
QList<QPolygonF> reducePoints( const double range,
                               QList<QPolygonF>& mwList,
                               const bool verbose )
{
  QPointF startP;
  QPointF lastP;
  double startBearing;
  QList<QPolygonF> retList;
  QList<QPointF> ignoreList;

  int sum = 0;

  for( int i = 0; i < mwList.size(); i++ )
    {
      const QPolygonF& plIn = mwList.at(i);
      QPolygonF plOut;

      for( int j = 0; j < plIn.size(); j++ )
        {
          const QPointF& p = plIn.at(j);

          if( j == 0 )
            {
              // Set start point for filtering
              startP = p;
              plOut.append(p);
              continue;
            }

          if( j == 1 )
            {
              startBearing = getBearingWgs( startP, p );
              lastP = p;
              continue;
            }

          // calculate bearing from start point
          double bearing = getBearingWgs( startP, p );

          // calculate distance from start point
          double dist = distP(startP.x(), startP.y(), p.x(), p.y());

          // calculate sector angle from start point.
          const double delta = atan( range / dist );

          if( fabs( startBearing - bearing ) < delta )
            {
              // Ignore point, it is laying inside the corridor.
              ignoreList.append(p);
              lastP = p;
              continue;
            }

#if 0
          printf( "j=%d, Start=%.1f, Entf=%.0f, Kurs=%.1f, Winkel=%.1f, Diff=%.1f°\n",
                   j, startBearing, dist, bearing, delta,
                   fabs( startBearing - bearing) * 180.0 / M_PI );
#endif
          // Add points from the ignore list to get a better turn
          int start = ignoreList.size() - 2;

          if( start < 0 )
            {
              start = 0;
            }

          if( start < ignoreList.size() )
            {
              // qDebug() << "IgnoreList" << ignoreList.size() << "is used";
            }

          for( int k=start; k < ignoreList.size(); k++ )
            {
              // plOut.append( ignoreList.at(k) );
            }

          ignoreList.clear();

          startBearing = bearing;
          plOut.append(lastP);
          startP = lastP;
          lastP = p;
        }

      if( plOut.size() > 0 && lastP != plOut.last() )
        {
          // Add last start point to the segment list.
          plOut.append(lastP);
        }

      if( plOut.size() < 2 )
        {
          qWarning() << "Polyline" << i << "has only" << plOut.size() << "points!";
          continue;
        }

      if( plIn.size() - plOut.size() )
        {
          if( verbose )
            {
              qDebug() << "Points=" << plIn.size()
                       << "Taken=" << plOut.size()
                       << "Reduced=" << (plIn.size() - plOut.size());
            }

          sum += plIn.size() - plOut.size();
        }

      retList.append( plOut );
    }

  qDebug() << "Corridor=" << range << "m," << sum << "points are removed.";

  return retList;
}