/* 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)); }
/* 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)); }
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)); }
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); }
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; } }
/* 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; } } } }
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; }