예제 #1
0
bool SnappingToolHelper::snapToDirection(MapCoordF position, MapWidget* widget, ConstrainAngleToolHelper* angle_tool, MapCoord* out_snap_position)
{
	// As getting a direction from the map grid is not supported, remove grid from filter
	int filter_grid = filter & GridCorners;
	filter = (SnapObjects)(filter & ~filter_grid);
	
	// Snap to position
	SnappingToolHelperSnapInfo info;
	MapCoord snap_position = snapToObject(position, widget, &info);
	if (out_snap_position)
		*out_snap_position = snap_position;
	
	// Add grid to filter again, if it was there originally
	filter = (SnapObjects)(filter | filter_grid);
	
	// Get direction from result
	switch (info.type)
	{
	case ObjectCorners:
		if (info.object->getType() == Object::Point)
		{
			const PointObject* point = info.object->asPoint();
			angle_tool->clearAngles();
			angle_tool->addAngles(point->getRotation() - M_PI/2, M_PI/2);
			return true;
		}
		else if (info.object->getType() == Object::Path)
		{
			const PathObject* path = info.object->asPath();
			angle_tool->clearAngles();
			bool ok;
			// Forward tangent
			MapCoordF tangent = path->findPartForIndex(info.coord_index)->calculateTangent(info.coord_index, false, ok);
			if (ok)
				angle_tool->addAngles(-tangent.angle(), M_PI/2);
			// Backward tangent
			tangent = path->findPartForIndex(info.coord_index)->calculateTangent(info.coord_index, true, ok);
			if (ok)
				angle_tool->addAngles(-tangent.angle(), M_PI/2);
			return true;
		}
		return false;
		
	case ObjectPaths:
		{
			const PathObject* path = info.object->asPath();
			angle_tool->clearAngles();
			auto part   = path->findPartForIndex(info.path_coord.index);
			auto split  = SplitPathCoord::at(part->path_coords, info.path_coord.clen);
			auto right = split.tangentVector().perpRight();
			angle_tool->addAngles(-right.angle(), M_PI/2);
		}
		return true;
		
	default:
		return false;
	}
}
예제 #2
0
void KoStarShape::updatePath( const QSizeF &size )
{
    Q_UNUSED(size);
    qreal radianStep = M_PI / static_cast<qreal>(m_cornerCount);

    createPoints( m_convex ? m_cornerCount : 2*m_cornerCount );

    KoSubpath &points = *m_subpaths[0];

    uint index = 0;
    for( uint i = 0; i < 2*m_cornerCount; ++i )
    {
        uint cornerType = i % 2;
        if( cornerType == base && m_convex )
            continue;
        qreal radian = static_cast<qreal>( (i+1)*radianStep ) + m_angles[cornerType];
        QPointF cornerPoint = QPointF( m_zoomX * m_radius[cornerType] * cos( radian ), m_zoomY * m_radius[cornerType] * sin( radian ) );

        points[index]->setPoint( m_center + cornerPoint );
        points[index]->unsetProperty( KoPathPoint::StopSubpath );
        points[index]->unsetProperty( KoPathPoint::CloseSubpath );
        if( m_roundness[cornerType] > 1e-10 || m_roundness[cornerType] < -1e-10 )
        {
            // normalized cross product to compute tangential vector for handle point
            QPointF tangentVector( cornerPoint.y()/m_radius[cornerType], -cornerPoint.x()/m_radius[cornerType] );
            points[index]->setControlPoint2( points[index]->point() - m_roundness[cornerType] * tangentVector );
            points[index]->setControlPoint1( points[index]->point() + m_roundness[cornerType] * tangentVector );
        }
        else
        {
            points[index]->removeControlPoint1();
            points[index]->removeControlPoint2();
        }
        index++;
    }

    // first path starts and closes path
    points[0]->setProperty( KoPathPoint::StartSubpath );
    points[0]->setProperty( KoPathPoint::CloseSubpath );
    // last point stops and closes path
    points.last()->setProperty( KoPathPoint::StopSubpath );
    points.last()->setProperty( KoPathPoint::CloseSubpath );

    normalize();

    m_handles.clear();
    m_handles.push_back( points.at(tip)->point() );
    if( ! m_convex )
        m_handles.push_back( points.at(base)->point() );

    m_center = computeCenter();
}
예제 #3
0
void PathObjectTest::atypicalPathTest()
{
	// This is a zero-length closed path of three arcs.
	MapCoordVector coords(10, {2.0, 2.0});
	coords[0].setCurveStart(true);
	coords[3].setCurveStart(true);
	coords[6].setCurveStart(true);
	coords[9].setClosePoint(true);
	coords[9].setHolePoint(true);
	
	PathCoordVector path_coords { coords };
	path_coords.update(0);
	QCOMPARE(path_coords.size(), (std::size_t)7u);
	
	for (std::size_t i = 0, end = path_coords.size(); i< end; ++i)
	{
		switch (i)
		{
		case 0:
			QCOMPARE(path_coords[i].index, 0u);
			QCOMPARE(path_coords[i].param, 0.0f);
			QCOMPARE(path_coords[i].clen, 0.0f);
			break;
		default:
			if (path_coords[i].param == 0.0)
				QVERIFY(path_coords[i-1].index < path_coords[i].index);
			else
				QVERIFY(path_coords[i-1].index == path_coords[i].index);
			QCOMPARE(path_coords[i].clen, 0.0f);
			break;
		case 9:
			QCOMPARE(path_coords[i].index, 9u);
			QCOMPARE(path_coords[i].param, 0.0f);
			QCOMPARE(path_coords[i].clen, 0.0f);
			break;
		}
		
		auto split = SplitPathCoord::at(path_coords, i);
		QCOMPARE((std::size_t)split.path_coord_index, i);
		auto tangent = split.tangentVector();
		Q_UNUSED(tangent)
	}
}