Example #1
0
void DrawPathTool::createPreviewCurve(MapCoord position, float direction)
{
	if (!path_has_preview_point)
	{
		int last = preview_path->getCoordinateCount() - 1;
		(preview_path->getCoordinate(last)).setCurveStart(true);
		
		preview_path->addCoordinate(MapCoord(0, 0));
		preview_path->addCoordinate(MapCoord(0, 0));
		if (draw_dash_points)
			position.setDashPoint(true);
		position.setCurveStart(false);
		preview_path->addCoordinate(position);
		
		path_has_preview_point = true;
	}
	
	// Adjust the preview curve
	int last = preview_path->getCoordinateCount() - 1;
	MapCoord previous_point = preview_path->getCoordinate(last - 3);
	MapCoord last_point = preview_path->getCoordinate(last);
	
	double bezier_handle_distance = BEZIER_HANDLE_DISTANCE * previous_point.distanceTo(last_point);
	
	preview_path->setCoordinate(last - 2, MapCoord(previous_point.x() - bezier_handle_distance * sin(previous_point_direction),
	                                               previous_point.y() - bezier_handle_distance * cos(previous_point_direction)));
	preview_path->setCoordinate(last - 1, MapCoord(last_point.x() + bezier_handle_distance * sin(direction),
	                                               last_point.y() + bezier_handle_distance * cos(direction)));
	updatePreviewPath();	
}
Example #2
0
TestMap::TestMap()
{
	MapCoord coord;
	
	map = new Map();
	
	MapColor* black = new MapColor();
	black->setCmyk(MapColorCmyk(0.0f, 0.0f, 0.0f, 1.0f));
	black->setOpacity(1.0f);
	black->setName("black");
	map->addColor(black, 0);
	
	line_symbol = new LineSymbol();
	line_symbol->setLineWidth(1);
	line_symbol->setColor(black);
	map->addSymbol(line_symbol, 0);
	
	line_object = new PathObject(line_symbol);
	line_object->addCoordinate(MapCoord(10, 10));
	coord = MapCoord(20, 10);
	coord.setCurveStart(true);
	line_object->addCoordinate(coord);
	line_object->addCoordinate(MapCoord(20, 20));
	line_object->addCoordinate(MapCoord(30, 20));
	line_object->addCoordinate(MapCoord(30, 10));
	map->addObject(line_object);
	
	// TODO: fill map with more content as needed
}
Example #3
0
void TransformTest::testTransformTranslate()
{
	MapCoord offset { 100.0, 100.0 };
	QTransform qt;
	qt.translate(offset.x(), offset.y());
	QVERIFY(qt.isTranslating());
	QCOMPARE(int(qt.type()), int(QTransform::TxTranslate));
	
	auto t = TemplateTransform::fromQTransform(qt);
	QCOMPARE(t.template_x, offset.nativeX());
	QCOMPARE(t.template_y, offset.nativeY());
	QCOMPARE(t.template_scale_x, 1.0);
	QCOMPARE(t.template_scale_y, 1.0);
	QCOMPARE(t.template_rotation, 0.0);
}
Example #4
0
void DrawPathTool::finishFollowing()
{
	following = false;
	
	int last = preview_path->getCoordinateCount() - 1;
	
	if (last >= 3 && preview_path->getCoordinate(last - 3).isCurveStart())
	{
		MapCoord first = preview_path->getCoordinate(last - 1);
		MapCoord second = preview_path->getCoordinate(last);
		
		previous_point_is_curve_point = true;
		previous_point_direction = -atan2(second.x() - first.x(), first.y() - second.y());
		previous_pos_map = MapCoordF(second);
		previous_drag_map = MapCoordF(second.x() + (second.x() - first.x()) / 2, second.y() + (second.y() - first.y()) / 2);
	}
	else
		previous_point_is_curve_point = false;
	
	updateAngleHelper();
}
Example #5
0
void DrawPathTool::closeDrawing()
{
	Q_ASSERT(editingInProgress());
	
	if (preview_path->getCoordinateCount() <= 1)
		return;
	
	if (previous_point_is_curve_point && preview_path->getCoordinate(0).isCurveStart())
	{
		// Finish with a curve
		path_has_preview_point = false;
		
		if (dragging)
			previous_point_direction = -atan2(cur_pos_map.x() - click_pos_map.x(), click_pos_map.y() - cur_pos_map.y());
		
		MapCoord first = preview_path->getCoordinate(0);
		MapCoord second = preview_path->getCoordinate(1);
		createPreviewCurve(first, -atan2(second.x() - first.x(), first.y() - second.y()));
		path_has_preview_point = false;
	}
	
	if (!preview_path->parts().empty())
		preview_path->parts().front().setClosed(true, true);
}
Example #6
0
void EditPointTool::clickPress()
{
	Q_ASSERT(!hover_state.testFlag(OverObjectNode) ||
	         !hover_state.testFlag(OverPathEdge) ||
	         hover_object);
	
	if (hover_state.testFlag(OverPathEdge) &&
	    active_modifiers & Qt::ControlModifier)
	{
		// Add new point to path
		PathObject* path = hover_object->asPath();
		
		float distance_sq;
		PathCoord path_coord;
		path->calcClosestPointOnPath(cur_pos_map, distance_sq, path_coord);
		
		float click_tolerance_map_sq = cur_map_widget->getMapView()->pixelToLength(clickTolerance());
		click_tolerance_map_sq = click_tolerance_map_sq * click_tolerance_map_sq;
		
		if (distance_sq <= click_tolerance_map_sq)
		{
			startEditing();
			QScopedValueRollback<bool> no_effect_rollback(no_more_effect_on_click);
			no_more_effect_on_click = true;
			startDragging();
			hover_state = OverObjectNode;
			hover_point = path->subdivide(path_coord);
			if (addDashPointDefault() ^ space_pressed)
			{
				MapCoord point = path->getCoordinate(hover_point);
				point.setDashPoint(true);
				path->setCoordinate(hover_point, point);
				map()->emitSelectionEdited();
			}
			startEditingSetup();
			updatePreviewObjects();
		}
	}
    else if (hover_state.testFlag(OverObjectNode) &&
	         hover_object->getType() == Object::Path)
	{
		PathObject* hover_object = this->hover_object->asPath();
		Q_ASSERT(hover_point < hover_object->getCoordinateCount());
		
		if (space_pressed &&
		    !hover_object->isCurveHandle(hover_point))
		{
			// Switch point between dash / normal point
			createReplaceUndoStep(hover_object);
			
			MapCoord& hover_coord = hover_object->getCoordinate(hover_point);
			hover_coord.setDashPoint(!hover_coord.isDashPoint());
			hover_object->update();
			updateDirtyRect();
			no_more_effect_on_click = true;
		}
		else if (active_modifiers & Qt::ControlModifier)
		{
			auto hover_point_part_index = hover_object->findPartIndexForIndex(hover_point);
			PathPart& hover_point_part = hover_object->parts()[hover_point_part_index];
			
			if (hover_object->isCurveHandle(hover_point))
			{
				// Convert the curve into a straight line
				createReplaceUndoStep(hover_object);
				hover_object->deleteCoordinate(hover_point, false);
				hover_object->update();
				map()->emitSelectionEdited();
				updateHoverState(cur_pos_map);
				updateDirtyRect();
				no_more_effect_on_click = true;
			}
			else
			{
				// Delete the point
				if (hover_point_part.countRegularNodes() <= 2 ||
				    ( !(hover_object->getSymbol()->getContainedTypes() & Symbol::Line) &&
				      hover_point_part.size() <= 3 ) )
				{
					// Not enough remaining points -> delete the part and maybe object
					if (hover_object->parts().size() == 1)
					{
						map()->removeObjectFromSelection(hover_object, false);
						auto undo_step = new AddObjectsUndoStep(map());
						auto part = map()->getCurrentPart();
						int index = part->findObjectIndex(hover_object);
						Q_ASSERT(index >= 0);
						undo_step->addObject(index, hover_object);
						map()->deleteObject(hover_object, true);
						map()->push(undo_step);
						map()->setObjectsDirty();
						map()->emitSelectionEdited();
						updateHoverState(cur_pos_map);
					}
					else
					{
						createReplaceUndoStep(hover_object);
						hover_object->deletePart(hover_point_part_index);
						hover_object->update();
						map()->emitSelectionEdited();
						updateHoverState(cur_pos_map);
						updateDirtyRect();
					}
					no_more_effect_on_click = true;
				}
				else
				{
					// Delete the point only
					createReplaceUndoStep(hover_object);
					int delete_bezier_spline_point_setting;
					if (active_modifiers & Qt::ShiftModifier)
						delete_bezier_spline_point_setting = Settings::EditTool_DeleteBezierPointActionAlternative;
					else
						delete_bezier_spline_point_setting = Settings::EditTool_DeleteBezierPointAction;
					hover_object->deleteCoordinate(hover_point, true, Settings::getInstance().getSettingCached((Settings::SettingsEnum)delete_bezier_spline_point_setting).toInt());
					hover_object->update();
					map()->emitSelectionEdited();
					updateHoverState(cur_pos_map);
					updateDirtyRect();
					no_more_effect_on_click = true;
				}
			}
		}
	}
	else if (hoveringOverSingleText())
	{
		TextObject* hover_object = map()->getFirstSelectedObject()->asText();
		startEditing();
		
		// Don't show the original text while editing
		map()->removeRenderablesOfObject(hover_object, true);
		
		// Make sure that the TextObjectEditorHelper remembers the correct standard cursor
		cur_map_widget->setCursor(getCursor());
		
		old_text = hover_object->getText();
		old_horz_alignment = (int)hover_object->getHorizontalAlignment();
		old_vert_alignment = (int)hover_object->getVerticalAlignment();
		text_editor = new TextObjectEditorHelper(hover_object, editor);
		connect(text_editor, SIGNAL(selectionChanged(bool)), this, SLOT(textSelectionChanged(bool)));
		
		// Select clicked position
		int pos = hover_object->calcTextPositionAt(cur_pos_map, false);
		text_editor->setSelection(pos, pos);
		
		updatePreviewObjects();
	}
	
	click_timer.restart();
}
Example #7
0
void PointHandles::draw(
        QPainter* painter,
        const MapWidget* widget,
        const Object* object,
        MapCoordVector::size_type hover_point,
        bool draw_curve_handles,
        PointHandleState base_state ) const
{
	if (object->getType() == Object::Point)
	{
		const PointObject* point = reinterpret_cast<const PointObject*>(object);
		draw(painter, widget->mapToViewport(point->getCoordF()), NormalHandle, (hover_point == 0) ? ActiveHandleState : base_state);
	}
	else if (object->getType() == Object::Text)
	{
		const TextObject* text = reinterpret_cast<const TextObject*>(object);
		std::vector<QPointF> text_handles(text->controlPoints());
		for (std::size_t i = 0; i < text_handles.size(); ++i)
			draw(painter, widget->mapToViewport(text_handles[i]), NormalHandle, (hover_point == i) ? ActiveHandleState : base_state);
	}
	else if (object->getType() == Object::Path)
	{
		painter->setBrush(Qt::NoBrush); // for handle lines
		
		const PathObject* path = reinterpret_cast<const PathObject*>(object);
		
		for (const auto& part : path->parts())
		{
			bool have_curve = part.isClosed() && part.size() > 3 && path->getCoordinate(part.last_index - 3).isCurveStart();
			PointHandleType handle_type = NormalHandle;
			
			for (auto i = part.first_index; i <= part.last_index; ++i)
			{
				MapCoord coord = path->getCoordinate(i);
				if (coord.isClosePoint())
					continue;
				QPointF point = widget->mapToViewport(coord);
				bool is_active = hover_point == i;
				
				if (i == part.first_index && !part.isClosed()) // || (i > part.start_index && path->getCoordinate(i-1).isHolePoint()))
					handle_type = StartHandle;
				else if (i == part.last_index && !part.isClosed()) // || coord.isHolePoint())
					handle_type = EndHandle;
				else
					handle_type = coord.isDashPoint() ? DashHandle : NormalHandle;
				
				// Draw incoming curve handle
				QPointF curve_handle;
				if (draw_curve_handles && have_curve)
				{
					auto curve_index = (i == part.first_index) ? (part.last_index - 1) : (i - 1);
					curve_handle = widget->mapToViewport(path->getCoordinate(curve_index));
					drawCurveHandleLine(painter, point, curve_handle, handle_type, is_active ? ActiveHandleState : base_state);
					draw(painter, curve_handle, CurveHandle, (is_active || hover_point == curve_index) ? ActiveHandleState : base_state);
					have_curve = false;
				}
				
				// Draw outgoing curve handle, first part
				if (draw_curve_handles && coord.isCurveStart())
				{
					curve_handle = widget->mapToViewport(path->getCoordinate(i+1));
					drawCurveHandleLine(painter, point, curve_handle,handle_type,  is_active ? ActiveHandleState : base_state);
				}
				
				// Draw point
				draw(painter, point, handle_type, is_active ? ActiveHandleState : base_state);
				
				// Draw outgoing curve handle, second part
				if (coord.isCurveStart())
				{
					if (draw_curve_handles)
					{
						draw(painter, curve_handle, CurveHandle, (is_active || hover_point == i + 1) ? ActiveHandleState : base_state);
						have_curve = true;
					}
					i += 2;
				}
			}
		}
	}
	else
		Q_ASSERT(false);
}
Example #8
0
bool DrawPathTool::mouseReleaseEvent(QMouseEvent* event, MapCoordF map_coord, MapWidget* widget)
{
	if (!isDrawingButton(event->button()))
		return false;

	left_mouse_down = false;
	
	if (picking_angle)
	{
		picking_angle = false;
		picked_angle = pickAngle(map_coord, widget);
		return true;
	}
	else if (!editingInProgress())
	{
		return false;
	}
	
	if (following)
	{
		finishFollowing();
		if ((event->button() == Qt::RightButton) && drawOnRightClickEnabled())
			finishDrawing();
		return true;
	}
	
	if (!create_segment)
		return true;
	
	if (previous_point_is_curve_point && !dragging && !create_spline_corner)
	{
		// The new point has not been added yet
		MapCoord coord;
		if (shift_pressed)
		{
			coord = snap_helper->snapToObject(map_coord, widget);
		}
		else if (angle_helper->isActive())
		{
			QPointF constrained_pos;
			angle_helper->getConstrainedCursorPositions(map_coord, constrained_pos_map, constrained_pos, widget);
			coord = MapCoord(constrained_pos_map);
		}
		else
		{
			coord = MapCoord(map_coord);
		}
		
		if (draw_dash_points)
			coord.setDashPoint(true);
		preview_path->addCoordinate(coord);
		updatePreviewPath();
		updateDirtyRect();
	}
	
	previous_point_is_curve_point = dragging;
	if (previous_point_is_curve_point)
	{
		QPointF constrained_pos;
		angle_helper->getConstrainedCursorPositions(map_coord, constrained_pos_map, constrained_pos, widget);
		
		previous_pos_map = click_pos_map;
		previous_drag_map = constrained_pos_map;
		previous_point_direction = calculateRotation(constrained_pos.toPoint(), constrained_pos_map);
	}
	
	updateAngleHelper();
	
	create_spline_corner = false;
	path_has_preview_point = false;
	dragging = false;
	
	if ((event->button() == Qt::RightButton) && drawOnRightClickEnabled())
		finishDrawing();
	return true;
}
Example #9
0
/**
 * Removes flags from the coordinate to be able to use it in the reconstruction.
 */
static MapCoord resetCoordinate(MapCoord in)
{
	in.setFlags(0);
	return in;
}
Example #10
0
/**
 * Compares a MapCoord and ClipperLib::IntPoint.
 */
bool operator==(const MapCoord& lhs, const ClipperLib::IntPoint& rhs)
{
	return lhs.nativeX() == rhs.X && lhs.nativeY() == rhs.Y;
}
Example #11
0
bool DrawRectangleTool::mousePressEvent(QMouseEvent* event, MapCoordF map_coord, MapWidget* widget)
{
	// Adjust flags to have possibly more recent state
	int modifiers = (event->modifiers() | (key_button_bar ? key_button_bar->activeModifiers() : 0));
	ctrl_pressed = modifiers & Qt::ControlModifier;
	shift_pressed = modifiers & Qt::ShiftModifier;
	cur_map_widget = widget;
	if (isDrawingButton(event->button()))
	{
		dragging = false;
		click_pos = event->pos();
		click_pos_map = map_coord;
		cur_pos = event->pos();
		cur_pos_map = click_pos_map;
		if (shift_pressed)
			cur_pos_map = MapCoordF(snap_helper->snapToObject(cur_pos_map, widget));
		constrained_pos_map = cur_pos_map;
		
		if (!editingInProgress())
		{
			if (ctrl_pressed)
			{
				// Pick direction
				pickDirection(cur_pos_map, widget);
			}
			else
			{
				// Start drawing
				if (angle_helper->isActive())
					angle_helper->setCenter(click_pos_map);
				startDrawing();
				MapCoord coord = MapCoord(cur_pos_map);
				coord.setDashPoint(draw_dash_points);
				preview_path->addCoordinate(coord);
				preview_path->addCoordinate(coord);
				angles.push_back(0);
				updateStatusText();
			}
		}
		else
		{
			if (angles.size() >= 2 && drawingParallelTo(angles[angles.size() - 2]))
			{
				// Drawing parallel to last section, just move the last point
				undoLastPoint();
			}
			
			// Add new point
			int cur_point_index = angles.size();
			if (!preview_path->getCoordinate(cur_point_index).isPositionEqualTo(preview_path->getCoordinate(cur_point_index - 1)))
			{
				MapCoord coord = MapCoord(cur_pos_map);
				coord.setDashPoint(draw_dash_points);
				preview_path->addCoordinate(coord);
				if (angles.size() == 1)
				{
					// Bring to correct number of points: line becomes a rectangle
					preview_path->addCoordinate(coord);
				}
				angles.push_back(0);
				
				angle_helper->setActive(true, MapCoordF(preview_path->getCoordinate(cur_point_index)));
				angle_helper->clearAngles();
				angle_helper->addAngles(angles[0], M_PI/4);
			
				if (event->button() != Qt::RightButton || !drawOnRightClickEnabled())
				{
					updateHover(false);
					updateHover(false); // Call it again, really.
				}
			}
		}
	}
	else if (event->button() == Qt::RightButton && editingInProgress())
	{
		constrained_pos_map = MapCoordF(preview_path->getCoordinate(angles.size() - 1));
		undoLastPoint();
		if (editingInProgress()) // despite undoLastPoint()
			finishDrawing();
		no_more_effect_on_click = true;
	}
	else
	{
		return false;
	}
	
	return true;
}
Example #12
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();
}
Example #13
0
void Template::setTemplatePosition(MapCoord coord)
{
	transform.template_x = coord.nativeX();
	transform.template_y = coord.nativeY();
	updateTransformationMatrices();
}
Example #14
0
#include <vector>
#include "nuvieDefs.h"
#include "DirFinder.h"
#include "AStarPath.h"
AStarPath::AStarPath() : final_node(0)
{}void AStarPath::create_path()
{    astar_node *i = final_node; // iterator through steps, from back
    delete_path();
    std::vector<astar_node *> reverse_list;
    while(i)
    {
        reverse_list.push_back(i);
        i = i->parent;
    }
    while(!reverse_list.empty())
    {
        i = reverse_list.back();
        add_step(i->loc);
        reverse_list.pop_back();
    }
    set_path_size(step_count);
}/* Get a new neighbor to nnode and score it, returning true if it's usable. */
bool AStarPath::score_to_neighbor(sint8 dir, astar_node *nnode, astar_node *neighbor,
                                  sint32 &nnode_to_neighbor)
{    sint8 sx = -1, sy = -1;
    DirFinder::get_adjacent_dir(sx, sy, dir); // sx,sy = neighbor -1,-1 + dir
    // get neighbor of nnode towards sx,sy, and cost to that neighbor
    neighbor->loc = nnode->loc.abs_coords(sx, sy);
    nnode_to_neighbor = step_cost(nnode->loc, neighbor->loc);
    if(nnode_to_neighbor == -1)
    {
        delete neighbor; // this neighbor is blocked
        return false;
    }
    return true;
}/* Compare a node's score to the start node to already scored neighbors. */
bool AStarPath::compare_neighbors(astar_node *nnode, astar_node *neighbor,
                                  sint32 nnode_to_neighbor, astar_node *in_open,
                                  astar_node *in_closed)
{    neighbor->to_start = nnode->to_start + nnode_to_neighbor;
     // ignore this neighbor if already checked and closer to start
    if((in_open && in_open->to_start <= neighbor->to_start)
       || (in_closed && in_closed->to_start <= neighbor->to_start))
    {
        delete neighbor;
        return false;
    }
    return true;
}/* Check all neighbors of a node (location) and save them to the "seen" list. */
bool AStarPath::search_node_neighbors(astar_node *nnode, MapCoord &goal,
                                      const uint32 max_score)
{    for(uint32 dir = 1; dir < 8; dir += 2)
    {
        astar_node *neighbor = new astar_node;
        sint32 nnode_to_neighbor = -1;
        if(!score_to_neighbor(dir, nnode, neighbor, nnode_to_neighbor))
            continue; // this neighbor is blocked
        astar_node *in_open = find_open_node(neighbor),
                   *in_closed = find_closed_node(neighbor);
        if(!compare_neighbors(nnode, neighbor, nnode_to_neighbor, in_open, in_closed))
            continue;
        neighbor->parent = nnode;
        neighbor->to_goal = path_cost_est(neighbor->loc, goal);
        neighbor->score = neighbor->to_start + neighbor->to_goal;
        neighbor->len = nnode->len + 1;
        if(neighbor->score > max_score)
        {
            delete neighbor; // too far away
            continue;
        }
        // take neighbor out of closed list and put into open list
        if(in_closed)
            remove_closed_node(in_closed);
        if(!in_open)
            push_open_node(neighbor);
    }
    return true;
}/* Do A* search of tiles to create a path from `start' to `goal'.
 * Don't search past nodes with a score over the max. score.
 * Create a partial path to low-score nodes with a distance-to-start over the
 * max_steps count, defined here. Actor may perform another search when needed.
 * Returns true if a path is created
 */bool AStarPath::path_search(MapCoord &start, MapCoord &goal)
{//DEBUG(0,LEVEL_DEBUGGING,"SEARCH: %d: %d,%d -> %d,%d\n",actor->get_actor_num(),start.x,start.y,goal.x,goal.y);
    astar_node *start_node = new astar_node;
    start_node->loc = start;
    start_node->to_start = 0;
    start_node->to_goal = path_cost_est(start, goal);
    start_node->score = start_node->to_start + start_node->to_goal;
    start_node->len = 0;
    push_open_node(start_node);
    const uint32 max_score = get_max_score(start_node->to_goal);
    const uint32 max_steps = 8*2*4; // walk up to four screen lengths before searching again
    while(!open_nodes.empty())
    {
        astar_node *nnode = pop_open_node(); // next closest
        if(nnode->loc == goal || nnode->len >= max_steps)
        {
	    if(nnode->loc != goal)
	        DEBUG(0,LEVEL_DEBUGGING,"out of steps, making partial path (nnode->len=%d)\n",nnode->len);
//DEBUG(0,LEVEL_DEBUGGING,"GOAL\n");
            final_node = nnode;
            create_path();
            delete_nodes();
            return(true); // reached goal - success
        }
        // check cardinal neighbors (starting at top going clockwise)
        search_node_neighbors(nnode, goal, max_score);
        // node and neighbors checked, put into closed
        closed_nodes.push_back(nnode);
    }
//DEBUG(0,LEVEL_DEBUGGING,"FAIL\n");
    delete_nodes();
    return(false); // out of open nodes - failure
}/* Return the cost of moving one step from `c1' to `c2', which is always 1. This
 * isn't very helpful, so subclasses should provide their own function.
 * Returns -1 if c2 is blocked. */
sint32 AStarPath::step_cost(MapCoord &c1, MapCoord &c2)
{    if(!pf->check_loc(c2.x, c2.y, c2.z)
       || c2.distance(c1) > 1)
            return(-1);
    return(1);
}/* Return an item in the list of closed nodes whose location matches `ncmp'.
Example #15
0
QPointF MapView::mapToView(MapCoord coords) const
{
	return QPointF(map_to_view.m11() * coords.x() + map_to_view.m12() * coords.y() + map_to_view.m13(),
	               map_to_view.m21() * coords.x() + map_to_view.m22() * coords.y() + map_to_view.m23());
}