Beispiel #1
0
std::unique_ptr<PathObject> FollowPathToolHelper::updateFollowing(const PathCoord& end_coord)
{
	std::unique_ptr<PathObject> result;
	
	if (path && path->findPartIndexForIndex(end_coord.index) == part_index)
	{
		// Update end_clen
		auto new_end_clen = end_coord.clen;
		const auto& part = path->parts()[part_index];
		if (part.isClosed())
		{
			// Positive length to add to end_clen to get to new_end_clen with wrapping
			auto path_length = part.length();
			auto forward_diff = fmod_pos(new_end_clen - end_clen, path_length);
			auto delta_forward = forward_diff >= 0 && forward_diff < 0.5f * path_length;
			
			if (delta_forward
			    && !drag_forward
			    && fmod_pos(end_clen - start_clen, path_length) > 0.5f * path_length
			    && fmod_pos(new_end_clen - start_clen, path_length) <= 0.5f * path_length )
			{
				drag_forward = true;
			}
			else if (!delta_forward
			         && drag_forward
			         && fmod_pos(end_clen - start_clen, path_length) <= 0.5f * path_length
			         && fmod_pos(new_end_clen - start_clen, path_length) > 0.5f * path_length)
			{
				drag_forward = false;
			}
		}
		else
		{
			drag_forward = new_end_clen >= start_clen;
		}
		
		end_clen = new_end_clen;
		if (end_clen != start_clen)
		{
			// Create output path
			result.reset(new PathObject { part });
			if (drag_forward)
			{
				result->changePathBounds(0, start_clen, end_clen);
			}
			else
			{
				result->changePathBounds(0, end_clen, start_clen);
				result->reverse();
			}
		}
	}
	
	return result;
}
Beispiel #2
0
void DrawRectangleTool::updateRectangle()
{
	double angle = angle_helper->getConstrainedCursorPosMap(constrained_pos_map, constrained_pos_map);
	
	if (angles.size() == 1)
	{
		// Update vectors and angles
		forward_vector = constrained_pos_map - MapCoordF(preview_path->getCoordinate(0));
		forward_vector.normalize();
		
		angles.back() = -forward_vector.angle();
		
		// Update rectangle
		MapCoord coord = MapCoord(constrained_pos_map);
		coord.setDashPoint(draw_dash_points);
		preview_path->setCoordinate(1, coord);
	}
	else
	{
		// Update vectors and angles
		forward_vector = MapCoordF::fromPolar(1.0, -angle);
		
		angles.back() = angle;
		
		// Update rectangle
		auto cur_point_index = angles.size();
		deleteClosePoint();
		
		float forward_dist = MapCoordF::dotProduct(forward_vector, constrained_pos_map - MapCoordF(preview_path->getCoordinate(cur_point_index - 1)));
		MapCoord coord = preview_path->getCoordinate(cur_point_index - 1) + MapCoord(forward_dist * forward_vector);
		
		snapped_to_line = false;
		float best_snap_distance_sq = std::numeric_limits<float>::max();
		if (ctrl_pressed && angles.size() > 2)
		{
			// Try to snap to existing lines
			MapCoord original_coord = coord;
			for (int i = 0; i < (int)angles.size() - 1; ++i)
			{
				MapCoordF direction(100, 0);
				direction.rotate(-angles[i]);
				
				int num_steps;
				double angle_step, angle_offset = 0;
				if (i == 0 || qAbs(qAbs(fmod_pos(angles[i], M_PI) - fmod_pos(angles[i-1], M_PI)) - (M_PI / 2)) < 0.1)
				{
					num_steps = 2;
					angle_step = M_PI/2;
				}
				else
				{
					num_steps = 4;
					angle_step = M_PI/4;
				}
				
				for (int k = 0; k < num_steps; ++k)
				{
					if (qAbs(fmod_pos(angle, M_PI) - fmod_pos(angles[i] - (angle_offset + k * angle_step), M_PI)) < 0.1)
						continue;
					
					MapCoordF rotated_direction = direction;
					rotated_direction.rotate(angle_offset + k * angle_step);
					
					QLineF a(QPointF(preview_path->getCoordinate(cur_point_index - 1)), MapCoordF(preview_path->getCoordinate(cur_point_index - 1)) + forward_vector);
					QLineF b(QPointF(preview_path->getCoordinate(i)), MapCoordF(preview_path->getCoordinate(i)) + rotated_direction);
					QPointF intersection_point;
					QLineF::IntersectType intersection_type = a.intersect(b, &intersection_point);
					if (intersection_type == QLineF::NoIntersection)
						continue;
					
					float snap_distance_sq = original_coord.distanceSquaredTo(MapCoord(intersection_point));
					if (snap_distance_sq > best_snap_distance_sq)
						continue;
					
					best_snap_distance_sq = snap_distance_sq;
					coord = MapCoord(intersection_point);
					snapped_to_line_a = coord;
					snapped_to_line_b = coord + MapCoord(rotated_direction);
					snapped_to_line = true;
				}
			}
		}
		
		coord.setDashPoint(draw_dash_points);
		preview_path->setCoordinate(cur_point_index, coord);
		
		auto close_vector = calculateClosingVector();
		float close_dist = MapCoordF::dotProduct(close_vector, MapCoordF(preview_path->getCoordinate(0) - preview_path->getCoordinate(cur_point_index)));
		coord = preview_path->getCoordinate(cur_point_index) + MapCoord(close_dist * close_vector);
		coord.setDashPoint(draw_dash_points);
		preview_path->setCoordinate(cur_point_index + 1, coord);
		
		preview_path->parts().front().setClosed(true, true);
	}
	
	updatePreviewPath();
	updateDirtyRect();
}
Beispiel #3
0
bool DrawRectangleTool::drawingParallelTo(double angle) const
{
	const double epsilon = 0.01;
	double cur_angle = angles[angles.size() - 1];
	return qAbs(fmod_pos(cur_angle, M_PI) - fmod_pos(angle, M_PI)) < epsilon;
}