Пример #1
0
/* Same as above, but all the coordinates are absolute */
static float dist_to_crns_abs(float co[2], float corners[4][2])
{
	float d1, d2, d3, d4;
	const float *v1 = corners[0], *v2 = corners[1];
	const float *v3 = corners[2], *v4 = corners[3];

	d1 = dist_squared_to_line_segment_v2(co, v1, v2);
	d2 = dist_squared_to_line_segment_v2(co, v2, v3);
	d3 = dist_squared_to_line_segment_v2(co, v3, v4);
	d4 = dist_squared_to_line_segment_v2(co, v4, v1);

	return sqrtf(min_ffff(d1, d2, d3, d4));
}
Пример #2
0
/* Distance to quad defined by it's corners, corners are relative to pos */
static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
{
	float d1, d2, d3, d4;
	float p[2] = {co[0] - pos[0], co[1] - pos[1]};
	const float *v1 = crns[0], *v2 = crns[1];
	const float *v3 = crns[2], *v4 = crns[3];

	d1 = dist_squared_to_line_segment_v2(p, v1, v2);
	d2 = dist_squared_to_line_segment_v2(p, v2, v3);
	d3 = dist_squared_to_line_segment_v2(p, v3, v4);
	d4 = dist_squared_to_line_segment_v2(p, v4, v1);

	return sqrtf(min_ffff(d1, d2, d3, d4));
}
Пример #3
0
static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
{
	float d1, d2, d3, d4;
	float p[2] = {co[0] - pos[0], co[1] - pos[1]};
	float v1[2] = {min[0], min[1]}, v2[2] = {max[0], min[1]};
	float v3[2] = {max[0], max[1]}, v4[2] = {min[0], max[1]};

	d1 = dist_squared_to_line_segment_v2(p, v1, v2);
	d2 = dist_squared_to_line_segment_v2(p, v2, v3);
	d3 = dist_squared_to_line_segment_v2(p, v3, v4);
	d4 = dist_squared_to_line_segment_v2(p, v4, v1);

	return sqrtf(min_ffff(d1, d2, d3, d4));
}
Пример #4
0
static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack *track,
                                             MovieTrackingMarker *UNUSED(marker),
                                             int coord, int scene_framenr, float val)
{
	MouseSelectUserData *data = userdata;
	float co[2] = {scene_framenr, val};

	if (data->has_prev) {
		float dist_sq = dist_squared_to_line_segment_v2(data->mouse_co, data->prev_co, co);

		if (data->track == NULL || dist_sq < data->min_dist_sq) {
			data->track = track;
			data->min_dist_sq = dist_sq;
			data->coord = coord;
			copy_v2_v2(data->min_co, co);
		}
	}

	data->has_prev = true;
	copy_v2_v2(data->prev_co, co);
}
Пример #5
0
static bool view3d_ruler_pick(RulerInfo *ruler_info, const float mval[2],
                              RulerItem **r_ruler_item, int *r_co_index)
{
	ARegion *ar = ruler_info->ar;
	RulerItem *ruler_item;

	float dist_best = RULER_PICK_DIST_SQ;
	RulerItem *ruler_item_best = NULL;
	int co_index_best = -1;

	for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) {
		float co_ss[3][2];
		float dist;
		int j;

		/* should these be checked? - ok for now not to */
		for (j = 0; j < 3; j++) {
			ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
		}

		if (ruler_item->flag & RULERITEM_USE_ANGLE) {
			dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]),
			              dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2]));
			if (dist < dist_best) {
				dist_best = dist;
				ruler_item_best = ruler_item;

				{
					const float dist_points[3] = {
					    len_squared_v2v2(co_ss[0], mval),
					    len_squared_v2v2(co_ss[1], mval),
					    len_squared_v2v2(co_ss[2], mval),
					};
					if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) {
						co_index_best = min_axis_v3(dist_points);
					}
					else {
						co_index_best = -1;
					}
				}
			}
		}
		else {
			dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]);
			if (dist < dist_best) {
				dist_best = dist;
				ruler_item_best = ruler_item;

				{
					const float dist_points[2] = {
					    len_squared_v2v2(co_ss[0], mval),
					    len_squared_v2v2(co_ss[2], mval),
					};
					if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) {
						co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2;
					}
					else {
						co_index_best = -1;
					}
				}
			}
		}
	}

	if (ruler_item_best) {
		*r_ruler_item = ruler_item_best;
		*r_co_index = co_index_best;
		return true;
	}
	else {
		*r_ruler_item = NULL;
		*r_co_index = -1;
		return false;
	}
}
Пример #6
0
/* this function is not exact, sometimes it returns false positives,
 * the main point of it is to clear out _almost_ all bucket/face non-intersections,
 * returning TRUE in corner cases is ok but missing an intersection is NOT.
 *
 * method used
 * - check if the center of the buckets bounding box is intersecting the face
 * - if not get the max radius to a corner of the bucket and see how close we
 *   are to any of the triangle edges.
 */
static bool layer_bucket_isect_test(
        MaskRasterLayer *layer, unsigned int face_index,
        const unsigned int bucket_x, const unsigned int bucket_y,
        const float bucket_size_x, const float bucket_size_y,
        const float bucket_max_rad_squared)
{
	unsigned int *face = layer->face_array[face_index];
	float (*cos)[3] = layer->face_coords;

	const float xmin = layer->bounds.xmin + (bucket_size_x * (float)bucket_x);
	const float ymin = layer->bounds.ymin + (bucket_size_y * (float)bucket_y);
	const float xmax = xmin + bucket_size_x;
	const float ymax = ymin + bucket_size_y;

	const float cent[2] = {(xmin + xmax) * 0.5f,
	                       (ymin + ymax) * 0.5f};

	if (face[3] == TRI_VERT) {
		const float *v1 = cos[face[0]];
		const float *v2 = cos[face[1]];
		const float *v3 = cos[face[2]];

		if (isect_point_tri_v2(cent, v1, v2, v3)) {
			return TRUE;
		}
		else {
			if ((dist_squared_to_line_segment_v2(cent, v1, v2) < bucket_max_rad_squared) ||
			    (dist_squared_to_line_segment_v2(cent, v2, v3) < bucket_max_rad_squared) ||
			    (dist_squared_to_line_segment_v2(cent, v3, v1) < bucket_max_rad_squared))
			{
				return TRUE;
			}
			else {
				// printf("skip tri\n");
				return FALSE;
			}
		}

	}
	else {
		const float *v1 = cos[face[0]];
		const float *v2 = cos[face[1]];
		const float *v3 = cos[face[2]];
		const float *v4 = cos[face[3]];

		if (isect_point_tri_v2(cent, v1, v2, v3)) {
			return TRUE;
		}
		else if (isect_point_tri_v2(cent, v1, v3, v4)) {
			return TRUE;
		}
		else {
			if ((dist_squared_to_line_segment_v2(cent, v1, v2) < bucket_max_rad_squared) ||
			    (dist_squared_to_line_segment_v2(cent, v2, v3) < bucket_max_rad_squared) ||
			    (dist_squared_to_line_segment_v2(cent, v3, v4) < bucket_max_rad_squared) ||
			    (dist_squared_to_line_segment_v2(cent, v4, v1) < bucket_max_rad_squared))
			{
				return TRUE;
			}
			else {
				// printf("skip quad\n");
				return FALSE;
			}
		}
	}
}
Пример #7
0
bool ED_mask_find_nearest_diff_point(const bContext *C,
                                     struct Mask *mask,
                                     const float normal_co[2],
                                     int threshold, bool feather,
                                     float tangent[2],
                                     const bool use_deform,
                                     const bool use_project,
                                     MaskLayer **masklay_r,
                                     MaskSpline **spline_r,
                                     MaskSplinePoint **point_r,
                                     float *u_r,
                                     float *score_r)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	MaskLayer *masklay, *point_masklay;
	MaskSpline *point_spline;
	MaskSplinePoint *point = NULL;
	float dist_best_sq = FLT_MAX, co[2];
	int width, height;
	float u = 0.0f;
	float scalex, scaley;

	ED_mask_get_size(sa, &width, &height);
	ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);

	co[0] = normal_co[0] * scalex;
	co[1] = normal_co[1] * scaley;

	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			int i;
			MaskSplinePoint *cur_point;

			for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points;
			     i < spline->tot_point;
			     i++, cur_point++)
			{
				float *diff_points;
				unsigned int tot_diff_point;

				diff_points = BKE_mask_point_segment_diff(spline, cur_point, width, height,
				                                          &tot_diff_point);

				if (diff_points) {
					int j, tot_point;
					unsigned int tot_feather_point;
					float *feather_points = NULL, *points;

					if (feather) {
						feather_points = BKE_mask_point_segment_feather_diff(spline, cur_point,
						                                                     width, height,
						                                                     &tot_feather_point);

						points = feather_points;
						tot_point = tot_feather_point;
					}
					else {
						points = diff_points;
						tot_point = tot_diff_point;
					}

					for (j = 0; j < tot_point - 1; j++) {
						float dist_sq, a[2], b[2];

						a[0] = points[2 * j] * scalex;
						a[1] = points[2 * j + 1] * scaley;

						b[0] = points[2 * j + 2] * scalex;
						b[1] = points[2 * j + 3] * scaley;

						dist_sq = dist_squared_to_line_segment_v2(co, a, b);

						if (dist_sq < dist_best_sq) {
							if (tangent)
								sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]);

							point_masklay = masklay;
							point_spline = spline;
							point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point;
							dist_best_sq = dist_sq;
							u = (float)j / tot_point;
						}
					}

					if (feather_points)
						MEM_freeN(feather_points);

					MEM_freeN(diff_points);
				}
			}
		}
	}

	if (point && dist_best_sq < threshold) {
		if (masklay_r)
			*masklay_r = point_masklay;

		if (spline_r)
			*spline_r = point_spline;

		if (point_r)
			*point_r = point;

		if (u_r) {
			/* TODO(sergey): Projection fails in some weirdo cases.. */
			if (use_project) {
				u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
			}

			*u_r = u;
		}

		if (score_r) {
			*score_r = dist_best_sq;
		}

		return true;
	}

	if (masklay_r)
		*masklay_r = NULL;

	if (spline_r)
		*spline_r = NULL;

	if (point_r)
		*point_r = NULL;

	return false;
}