//---------------------------------------------------------- void ScreenItemAdd::addStraightArrowWave(int o, int /*duration*/, float density) { float freq = 1.0/density; float c = SRAND; EnemyWave straightArrow(EnemyStraight); straightArrow.setInOut(o, o+130); straightArrow.setXRand(0.0); straightArrow.setPos(c, 10.0); straightArrow.setFrequency((int)(50*freq), 0); straightArrow.setXRand(1.6); straightArrow.setFormation(EnemyWave::Arrow); addWave(straightArrow); EnemyWave omniWave(EnemyOmni); omniWave.setFrequency((int)(15*freq), 5); omniWave.setPos(c, 9.0); omniWave.setXRand(2.0); omniWave.setInOut(o+220, o+260); addWave(omniWave); omniWave.setXRand(3.0); omniWave.setFrequency((int)(22*freq), 5); omniWave.setInOut(o+440, o+600); addWave(omniWave); }
//---------------------------------------------------------- void ScreenItemAdd::addGnatWave(int o, int duration, float density, bool mixed) { float freq = 1.0/density; float c = -FRAND*3.0; if(mixed) { EnemyWave straightArrow(EnemyStraight); straightArrow.setInOut(o+50, o+duration); straightArrow.setXRand(0.0); straightArrow.setPos(c, 10.0); straightArrow.setFrequency((int)(90*freq), 20); straightArrow.setXRand(8.0); if(c > 0.0) { addWave(straightArrow); } else { EnemyWave omniArrow(EnemyOmni); omniArrow.setInOut(o+50, o+130); omniArrow.setPos(c, 10.0); omniArrow.setFrequency((int)(20*freq), 0); omniArrow.setXRand(1.1); addWave(omniArrow); omniArrow.setInOut(o+320, o+400); addWave(omniArrow); straightArrow.setInOut(o+200, o+250); addWave(straightArrow); } EnemyWave gnatWave(EnemyGnat); // gnatWave.setInOut(o, o+(17*game->gameSkill)*(1.0+FRAND*0.2)); gnatWave.setInOut(o, o+(int)((25*game->gameSkill)*(1.0+FRAND*0.2))); gnatWave.setPos(SRAND*5.0, 10.0); gnatWave.setFrequency((int)(3*freq), 0); gnatWave.setXRand(3.0); addWave(gnatWave); } else { EnemyWave gnatWave(EnemyGnat); // gnatWave.setInOut(o, o+(17*game->gameSkill)*(1.0+FRAND*0.2)); gnatWave.setPos(-3.0+SRAND*5.0, 10.0); gnatWave.setFrequency((int)(1*freq), 0); gnatWave.setXRand(3.0); gnatWave.setInOut(o, o+35); addWave(gnatWave); gnatWave.setPos(SRAND*5.0, 10.0); gnatWave.setInOut(o+300, o+310); addWave(gnatWave); gnatWave.setFrequency((int)(30*freq), 0); gnatWave.setInOut(o+300, o+400); addWave(gnatWave); } }
void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context ) { Q_UNUSED( points ); if ( !context.renderContext().painter() ) { return; } context.renderContext().expressionContext().appendScope( mExpressionScope.data() ); mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT, points.size() + 1 ); mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, 1 ); if ( isCurved() ) { for ( int pIdx = 0; pIdx < points.size() - 1; pIdx += 2 ) { mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 ); _resolveDataDefined( context ); if ( points.size() - pIdx >= 3 ) { // origin point QPointF po( points.at( pIdx ) ); // middle point QPointF pm( points.at( pIdx + 1 ) ); // destination point QPointF pd( points.at( pIdx + 2 ) ); QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadSize, mComputedHeadType, mScaledOffset ); mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() ); } // straight arrow else if ( points.size() - pIdx == 2 ) { // origin point QPointF po( points.at( pIdx ) ); // destination point QPointF pd( points.at( pIdx + 1 ) ); QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadSize, mComputedHeadType, mScaledOffset ); mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() ); } } } else { // only straight arrows for ( int pIdx = 0; pIdx < points.size() - 1; pIdx++ ) { mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 ); _resolveDataDefined( context ); // origin point QPointF po( points.at( pIdx ) ); // destination point QPointF pd( points.at( pIdx + 1 ) ); QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadSize, mComputedHeadType, mScaledOffset ); mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() ); } } context.renderContext().expressionContext().popScope(); }
QPolygonF curvedArrow( QPointF po, QPointF pm, QPointF pd, qreal startWidth, qreal width, qreal headSize, QgsArrowSymbolLayer::HeadType headType, qreal offset ) { qreal circleRadius; QPointF circleCenter; if ( ! pointsToCircle( po, pm, pd, circleCenter, circleRadius ) || circleRadius > 10000.0 ) { // aligned points => draw a straight arrow return straightArrow( po, pd, startWidth, width, headSize, headType, offset ); } // angles of each point qreal angle_o = clampAngle( atan2( circleCenter.y() - po.y(), po.x() - circleCenter.x() ) ); qreal angle_m = clampAngle( atan2( circleCenter.y() - pm.y(), pm.x() - circleCenter.x() ) ); qreal angle_d = clampAngle( atan2( circleCenter.y() - pd.y(), pd.x() - circleCenter.x() ) ); // arc direction : 1 = counter-clockwise, -1 = clockwise int direction = clampAngle( angle_m - angle_o ) < clampAngle( angle_m - angle_d ) ? 1 : -1; qreal deltaAngle = angle_d - angle_o; if ( direction * deltaAngle < 0.0 ) deltaAngle = deltaAngle + direction * 2 * M_PI; qreal length = euclidian_distance( po, pd ); // for close points and deltaAngle < 180, draw a straight line if ( fabs( deltaAngle ) < M_PI && ((( headType == QgsArrowSymbolLayer::HeadSingle ) && ( length < headSize ) ) || (( headType == QgsArrowSymbolLayer::HeadReversed ) && ( length < headSize ) ) || (( headType == QgsArrowSymbolLayer::HeadDouble ) && ( length < 2*headSize ) ) ) ) { return straightArrow( po, pd, startWidth, width, headSize, headType, offset ); } // ajust coordinates to include offset circleRadius += offset; po = circlePoint( circleCenter, circleRadius, angle_o ); pm = circlePoint( circleCenter, circleRadius, angle_m ); pd = circlePoint( circleCenter, circleRadius, angle_d ); qreal headAngle = direction * atan( headSize / circleRadius ); QPainterPath path; if ( headType == QgsArrowSymbolLayer::HeadDouble ) { // the first head path.moveTo( po ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_o + headAngle ) ); pathArcTo( path, circleCenter, circleRadius + direction * width / 2, angle_o + headAngle, angle_d - headAngle, direction ); // the second head path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_d - headAngle ) ); path.lineTo( pd ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_d - headAngle ) ); pathArcTo( path, circleCenter, circleRadius - direction * width / 2, angle_d - headAngle, angle_o + headAngle, -direction ); // the end of the first head path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_o + headAngle ) ); path.lineTo( po ); } else if ( headType == QgsArrowSymbolLayer::HeadSingle ) { path.moveTo( circlePoint( circleCenter, circleRadius + direction * startWidth / 2, angle_o ) ); spiralArcTo( path, circleCenter, angle_o, circleRadius + direction * startWidth / 2, angle_d - headAngle, circleRadius + direction * width / 2, direction ); // the arrow head path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_d - headAngle ) ); path.lineTo( pd ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_d - headAngle ) ); spiralArcTo( path, circleCenter, angle_d - headAngle, circleRadius - direction * width / 2, angle_o, circleRadius - direction * startWidth / 2, -direction ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * startWidth / 2, angle_o ) ); } else if ( headType == QgsArrowSymbolLayer::HeadReversed ) { path.moveTo( circlePoint( circleCenter, circleRadius + direction * width / 2, angle_o + headAngle ) ); spiralArcTo( path, circleCenter, angle_o + headAngle, circleRadius + direction * width / 2, angle_d, circleRadius + direction * startWidth / 2, direction ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * startWidth / 2, angle_d ) ); spiralArcTo( path, circleCenter, angle_d, circleRadius - direction * startWidth / 2, angle_o + headAngle, circleRadius - direction * width / 2, - direction ); path.lineTo( circlePoint( circleCenter, circleRadius - direction * headSize, angle_o + headAngle ) ); path.lineTo( po ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * headSize, angle_o + headAngle ) ); path.lineTo( circlePoint( circleCenter, circleRadius + direction * width / 2, angle_o + headAngle ) ); } return path.toSubpathPolygons().at( 0 ); }