Example #1
0
    inline std::tuple
        <
            distance_from_start_to_point<typename arithmetic_type_of<Polyline>::type>
          , distance_from_point_to_end<typename arithmetic_type_of<Polyline>::type>
          , polyline_segment_index
        > point_on_polyline_length_characteristics(const Polyline& P, const Point& p, const NumberComparisonPolicy& cmp)
    {
        using access = point_sequence_traits<Polyline>;
        using length_t = typename arithmetic_type_of<Polyline>::type;
        length_t length = constants::zero<length_t>(), postLength = constants::zero<length_t>();
        std::size_t size = access::size(P), index = (std::numeric_limits<std::size_t>::max)();
        for (std::size_t i = 0, j = 1; j < size; ++i, ++j)
        {
            auto A = access::get_point(P, i);
            auto B = access::get_point(P, j);
            if (index == (std::numeric_limits<std::size_t>::max)())
            {
                if (!is_between(A, B, p, true, cmp))
                    length += point_point_distance(A, B);
                else
                {
                    index = i;
                    length += point_point_distance(A, p);
                    postLength += point_point_distance(p, B);
                }
            }
            else
                postLength += point_point_distance(A, B);
        }

        return std::make_tuple(distance_from_start_to_point<length_t>(length), distance_from_point_to_end<length_t>(postLength), polyline_segment_index(index));
    }
inline oriented_bounding_box<Point, Vector> make_obb(const rectangle<Point>& r)
{
    auto uWidth = point_point_distance(r[1], r[0]);
    Vector u = construct<Vector>((r[1] - r[0]) / uWidth);
    auto vWidth = point_point_distance(r[3], r[0]);
    Vector v = construct<Vector>((r[3] - r[0]) / vWidth);
    uWidth *= 0.5;
    vWidth *= 0.5;
    return oriented_bounding_box<Point, Vector>(r[0] + uWidth * u + vWidth * v, u, v, uWidth, vWidth);
}
Example #3
0
static double computeDistance(bool isLeaf, BOX * box, Point * point)
{
	double result = 0.0;

	if (isLeaf) {
		/* simple point to point distance */
		result = point_point_distance(point, &box->low);
	} else if (point->x <= box->high.x && point->x >= box->low.x &&
		   point->y <= box->high.y && point->y >= box->low.y) {
		/* point inside the box */
		result = 0.0;
	} else if (point->x <= box->high.x && point->x >= box->low.x) {
		/* point is over or below box */
		ASSERT(box->low.y <= box->high.y);
		if (point->y > box->high.y)
			result = point->y - box->high.y;
		else if (point->y < box->low.y)
			result = box->low.y - point->y;
		else
			elog(ERROR, "inconsistent point values");
	} else if (point->y <= box->high.y && point->y >= box->low.y) {
		/* point is to left or right of box */
		ASSERT(box->low.x <= box->high.x);
		if (point->x > box->high.x)
			result = point->x - box->high.x;
		else if (point->x < box->low.x)
			result = box->low.x - point->x;
		else
			elog(ERROR, "inconsistent point values");
	} else {
		/* closest point will be a vertex */
		Point p;
		double subresult;

		result = point_point_distance(point, &box->low);
		subresult = point_point_distance(point, &box->high);
		if (result > subresult)
			result = subresult;

		p.x = box->low.x;
		p.y = box->high.y;
		subresult = point_point_distance(point, &p);
		if (result > subresult)
			result = subresult;

		p.x = box->high.x;
		p.y = box->low.y;
		subresult = point_point_distance(point, &p);
		if (result > subresult)
			result = subresult;
	}

	return result;
}
Example #4
0
// TODO: why another version?
// point_line_dist
float
point_line_dist(BPoint start, BPoint end, BPoint p, float radius)
{
	BRect r(min_c(start.x, end.x), min_c(start.y, end.y), max_c(start.x, end.x),
		max_c(start.y, end.y));
	r.InsetBy(-radius, -radius);
	if (r.Contains(p)) {
		return fabs(agg::calc_line_point_distance(start.x, start.y, end.x, end.y,
			p.x, p.y));
	}

	return min_c(point_point_distance(start, p), point_point_distance(end, p));
}
Example #5
0
// point_line_distance
double
point_line_distance(BPoint point, BPoint pa, BPoint pb)
{
	// first figure out if point is between segment start and end points
	double a = point_point_distance(point, pb);
	double b = point_point_distance(point, pa);
	double c = point_point_distance(pa, pb);

	float currentDist = min_c(a, b);

	if (a > 0.0 && b > 0.0) {
		double alpha = acos((b*b + c*c - a*a) / (2*b*c));
		double beta = acos((a*a + c*c - b*b) / (2*a*c));

		if (alpha <= M_PI_2 && beta <= M_PI_2) {
			currentDist = fabs(point_line_distance(pa.x, pa.y, pb.x, pb.y,
				point.x, point.y));
		}
	}

	return currentDist;
}
Example #6
0
    inline typename geometric_traits<typename point_sequence_traits<Polygon>::point_type>::arithmetic_type polygon_length(const Polygon& poly)
    {
        typedef point_sequence_traits<Polygon> access;
        typedef typename point_sequence_traits<Polygon>::point_type point_type;
        typedef typename geometric_traits<point_type>::arithmetic_type length_t;
        length_t length = constants::zero<length_t>();
        std::size_t size = access::size(poly);
        for (std::size_t i = 0, j = 1; i < size; ++i, j = (j+1)%size)
        {
            length += point_point_distance(access::get_point(poly, i), access::get_point(poly, j));
        }

        return length;
    }
Example #7
0
// calc_angle
double
calc_angle(BPoint origin, BPoint from, BPoint to, bool degree)
{
	double angle = 0.0;

	double d = point_line_distance(from.x, from.y, origin.x, origin.y,
		to.x, to.y);
	if (d != 0.0) {
		double a = point_point_distance(from, to);
		double b = point_point_distance(from, origin);
		double c = point_point_distance(to, origin);
		if (a > 0.0 && b > 0.0 && c > 0.0) {
			angle = acos((b*b + c*c - a*a) / (2.0*b*c));

			if (d < 0.0)
				angle = -angle;

			if (degree)
				angle = angle * 180.0 / M_PI;
		}
	}
	return angle;
}
Example #8
0
// _SetModeForMousePos
void
PathManipulator::_SetModeForMousePos(BPoint where)
{
	uint32 mode = UNDEFINED;
	int32 index = -1;

	float zoomLevel = fCanvasView->ZoomLevel();

	// see if we're close enough at a control point
	BPoint point;
	BPoint pointIn;
	BPoint pointOut;
	for (int32 i = 0; fPath->GetPointsAt(i, point, pointIn, pointOut)
					  && mode == UNDEFINED; i++) {

		float distM = point_point_distance(point, where) * zoomLevel;
		float distIn = point_point_distance(pointIn, where) * zoomLevel;
		float distOut = point_point_distance(pointOut, where) * zoomLevel;
		
		if (distM < MOVE_THRESHOLD) {
			if (i == 0 && fClickToClose
				&& !fPath->IsClosed() && fPath->CountPoints() > 1) {
				mode = fCommandDown ? TOGGLE_SHARP :
							(fOptionDown ? REMOVE_POINT : CLOSE_PATH);
				index = i;
			} else {
				mode = fCommandDown ? TOGGLE_SHARP :
							(fOptionDown ? REMOVE_POINT : MOVE_POINT);
				index = i;
			}
		}
		if (distM - distIn > 0.00001
			&& distIn < MOVE_THRESHOLD) {
			mode = fCommandDown ? TOGGLE_SHARP_IN : 
						(fOptionDown ? REMOVE_POINT_IN : MOVE_POINT_IN);
			index = i;
		}
		if (distIn - distOut > 0.00001
			&& distOut < distM && distOut < MOVE_THRESHOLD) {
			mode = fCommandDown ? TOGGLE_SHARP_OUT :
						(fOptionDown ? REMOVE_POINT_OUT : MOVE_POINT_OUT);
			index = i;
		}
	}
	// selection mode overrides any other mode,
	// but we need to check for it after we know
	// the index of the point under the mouse (code above)
	int32 pointCount = fPath->CountPoints();
	if (fShiftDown && pointCount > 0) {
		mode = SELECT_POINTS;
	}

	// see if user wants to start new sub path
	if (fAltDown) {
		mode = NEW_PATH;
		index = -1;
	}

	// see if we're close enough at a line
	if (mode == UNDEFINED) {
		float distance;
		if (fPath->GetDistance(where, &distance, &index)) {
			if (distance < (INSERT_DIST_THRESHOLD / zoomLevel)) {
				mode = INSERT_POINT;
			}
		} else {
			// restore index, since it was changed by call above
			index = fCurrentPathPoint;
		}
	}

	// nope, still undefined mode, last fall back
	if (mode == UNDEFINED) {
		if (fFallBackMode == SELECT_POINTS) {
			if (fPath->IsClosed() && pointCount > 0) {
				mode = SELECT_POINTS;
				index = -1;
			} else {
				mode = ADD_POINT;
				index = pointCount - 1;
			}
		} else {
			// user had clicked "New Path" icon
			mode = fFallBackMode;
		}
	}
	// switch mode if necessary
	if (mode != fMode || index != fCurrentPathPoint) {
		// invalidate path display (to highlight the respective point)
		_InvalidateHighlightPoints(index, mode);
		_SetMode(mode);
		fCurrentPathPoint = index;
	}
}
Example #9
0
// _DragStateFor
//! where is expected in canvas view coordinates
DragState*
TransformBox::_DragStateFor(BPoint where, float canvasZoom)
{
	DragState* state = NULL;
	// convert to canvas zoom level
	//
	// the conversion is necessary, because the "hot regions"
	// around a point should be the same size no matter what
	// zoom level the canvas is displayed at

	float inset = INSET / canvasZoom;

	// priorities:
	// transformation center point has highest priority ?!?
	if (point_point_distance(where, fPivot) < inset)
		state = fOffsetCenterState;

	if (!state) {
		// next, the inner area of the box

		// for the following calculations
		// we can apply the inverse transformation to all points
		// this way we have to consider BRects only, not transformed polygons
		BPoint lt = fLeftTop;
		BPoint rb = fRightBottom;
		BPoint w = where;

		InverseTransform(&w);
		InverseTransform(&lt);
		InverseTransform(&rb);

		// next priority has the inside of the box
		BRect iR(lt, rb);
		float hInset = min_c(inset, max_c(0, (iR.Width() - inset) / 2.0));
		float vInset = min_c(inset, max_c(0, (iR.Height() - inset) / 2.0));

		iR.InsetBy(hInset, vInset);
		if (iR.Contains(w))
			state = fTranslateState;
	}

	if (!state) {
		// next priority have the corners
		float dLT = point_point_distance(fLeftTop, where);
		float dRT = point_point_distance(fRightTop, where);
		float dLB = point_point_distance(fLeftBottom, where);
		float dRB = point_point_distance(fRightBottom, where);
		float d = min4(dLT, dRT, dLB, dRB);
		if (d < inset) {
			if (d == dLT)
				state = fDragLTState;
			else if (d == dRT)
				state = fDragRTState;
			else if (d == dLB)
				state = fDragLBState;
			else if (d == dRB)
				state = fDragRBState;
		}
	}

	if (!state) {
		// next priority have the sides
		float dL = point_line_dist(fLeftTop, fLeftBottom, where, inset);
		float dR = point_line_dist(fRightTop, fRightBottom, where, inset);
		float dT = point_line_dist(fLeftTop, fRightTop, where, inset);
		float dB = point_line_dist(fLeftBottom, fRightBottom, where, inset);
		float d = min4(dL, dR, dT, dB);
		if (d < inset) {
			if (d == dL)
				state = fDragLState;
			else if (d == dR)
				state = fDragRState;
			else if (d == dT)
				state = fDragTState;
			else if (d == dB)
				state = fDragBState;
		}
	}

	if (!state) {
		BPoint lt = fLeftTop;
		BPoint rb = fRightBottom;
		BPoint w = where;

		InverseTransform(&w);
		InverseTransform(&lt);
		InverseTransform(&rb);

		// check inside of the box again
		BRect iR(lt, rb);
		if (iR.Contains(w)) {
			state = fTranslateState;
		} else {
			// last priority has the rotate state
			state = fRotateState;
		}
	}

	return state;
}