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; } }
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(); }
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) } }