static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObject *args) { VectorObject *line_a1, *line_a2, *line_b1, *line_b2; float vi[2]; if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line_2d", &vector_Type, &line_a1, &vector_Type, &line_a2, &vector_Type, &line_b1, &vector_Type, &line_b2)) { return NULL; } if (BaseMath_ReadCallback(line_a1) == -1 || BaseMath_ReadCallback(line_a2) == -1 || BaseMath_ReadCallback(line_b1) == -1 || BaseMath_ReadCallback(line_b2) == -1) { return NULL; } if (isect_seg_seg_v2_point(line_a1->vec, line_a2->vec, line_b1->vec, line_b2->vec, vi) == 1) { return Vector_CreatePyObject(vi, 2, Py_NEW, NULL); } else { Py_RETURN_NONE; } }
static bool testVoronoiEdge(const float site[2], const float point[2], const VoronoiEdge *edge) { float p[2]; if (isect_seg_seg_v2_point(site, point, edge->start, edge->end, p) == 1) { if (len_squared_v2v2(p, edge->start) > VORONOI_EPS && len_squared_v2v2(p, edge->end) > VORONOI_EPS) { return false; } } return true; }
static void voronoi_clampEdgeVertex(int width, int height, float *coord, float *other_coord) { const float corners[4][2] = { {0.0f, 0.0f}, {width - 1, 0.0f}, {width - 1, height - 1}, {0.0f, height - 1}}; int i; if (IN_RANGE_INCL(coord[0], 0, width - 1) && IN_RANGE_INCL(coord[1], 0, height - 1)) { return; } for (i = 0; i < 4; i++) { float v1[2], v2[2]; float p[2]; copy_v2_v2(v1, corners[i]); if (i == 3) { copy_v2_v2(v2, corners[0]); } else { copy_v2_v2(v2, corners[i + 1]); } if (isect_seg_seg_v2_point(v1, v2, coord, other_coord, p) == 1) { if (i == 0 && coord[1] > p[1]) { continue; } if (i == 1 && coord[0] < p[0]) { continue; } if (i == 2 && coord[1] < p[1]) { continue; } if (i == 3 && coord[0] > p[0]) { continue; } copy_v2_v2(coord, p); } } }
static void feather_bucket_check_intersect( float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket, int cur_a, int cur_b) { int i; const float *v1 = (float *) feather_points[cur_a]; const float *v2 = (float *) feather_points[cur_b]; for (i = 0; i < bucket->tot_segment; i++) { int check_a = bucket->segments[i][0]; int check_b = bucket->segments[i][1]; const float *v3 = (float *) feather_points[check_a]; const float *v4 = (float *) feather_points[check_b]; if (check_a >= cur_a - 1 || cur_b == check_a) continue; if (isect_seg_seg_v2_simple(v1, v2, v3, v4)) { int k; float p[2]; float min_a[2], max_a[2]; float min_b[2], max_b[2]; isect_seg_seg_v2_point(v1, v2, v3, v4, p); INIT_MINMAX2(min_a, max_a); INIT_MINMAX2(min_b, max_b); /* collapse loop with smaller AABB */ for (k = 0; k < tot_feather_point; k++) { if (k >= check_b && k <= cur_a) { minmax_v2v2_v2(min_a, max_a, feather_points[k]); } else { minmax_v2v2_v2(min_b, max_b, feather_points[k]); } } if (max_a[0] - min_a[0] < max_b[0] - min_b[0] || max_a[1] - min_a[1] < max_b[1] - min_b[1]) { for (k = check_b; k <= cur_a; k++) { copy_v2_v2(feather_points[k], p); } } else { for (k = 0; k <= check_a; k++) { copy_v2_v2(feather_points[k], p); } if (cur_b != 0) { for (k = cur_b; k < tot_feather_point; k++) { copy_v2_v2(feather_points[k], p); } } } } } }
static bool scanfill_preprocess_self_isect( ScanFillContext *sf_ctx, PolyInfo *poly_info, const unsigned short poly_nr, ListBase *filledgebase) { PolyInfo *pi = &poly_info[poly_nr]; GHash *isect_hash = NULL; ListBase isect_lb = {NULL}; /* warning, O(n2) check here, should use spatial lookup */ { ScanFillEdge *eed; for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { ScanFillEdge *eed_other; for (eed_other = eed->next; eed_other; eed_other = (eed_other == pi->edge_last) ? NULL : eed_other->next) { if (!ELEM(eed->v1, eed_other->v1, eed_other->v2) && !ELEM(eed->v2, eed_other->v1, eed_other->v2) && (eed != eed_other)) { /* check isect */ float pt[2]; BLI_assert(eed != eed_other); if (isect_seg_seg_v2_point(eed->v1->co, eed->v2->co, eed_other->v1->co, eed_other->v2->co, pt) == 1) { ScanFillIsect *isect; if (UNLIKELY(isect_hash == NULL)) { isect_hash = BLI_ghash_ptr_new(__func__); } isect = MEM_mallocN(sizeof(ScanFillIsect), __func__); BLI_addtail(&isect_lb, isect); copy_v2_v2(isect->co, pt); isect->co[2] = eed->v1->co[2]; isect->v = BLI_scanfill_vert_add(sf_ctx, isect->co); isect->v->poly_nr = eed->v1->poly_nr; /* NOTE: vert may belong to 2 polys now */ VFLAG_SET(isect->v, V_ISISECT); edge_isect_ls_add(isect_hash, eed, isect); edge_isect_ls_add(isect_hash, eed_other, isect); } } } } } if (isect_hash == NULL) { return false; } /* now subdiv the edges */ { ScanFillEdge *eed; for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { if (eed->user_flag & E_ISISECT) { ListBase *e_ls = BLI_ghash_lookup(isect_hash, eed); LinkData *isect_link; /* maintain coorect terminating edge */ if (pi->edge_last == eed) { pi->edge_last = NULL; } if (BLI_listbase_is_single(e_ls) == false) { BLI_sortlist_r(e_ls, eed->v2->co, edge_isect_ls_sort_cb); } /* move original edge to filledgebase and add replacement * (which gets subdivided next) */ { ScanFillEdge *eed_tmp; eed_tmp = BLI_scanfill_edge_add(sf_ctx, eed->v1, eed->v2); BLI_remlink(&sf_ctx->filledgebase, eed_tmp); BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_tmp); BLI_remlink(&sf_ctx->filledgebase, eed); BLI_addtail(filledgebase, eed); if (pi->edge_first == eed) { pi->edge_first = eed_tmp; } eed = eed_tmp; } for (isect_link = e_ls->first; isect_link; isect_link = isect_link->next) { ScanFillIsect *isect = isect_link->data; ScanFillEdge *eed_subd; eed_subd = BLI_scanfill_edge_add(sf_ctx, isect->v, eed->v2); eed_subd->poly_nr = poly_nr; eed->v2 = isect->v; BLI_remlink(&sf_ctx->filledgebase, eed_subd); BLI_insertlinkafter(&sf_ctx->filledgebase, eed, eed_subd); /* step to the next edge and continue dividing */ eed = eed_subd; } BLI_freelistN(e_ls); MEM_freeN(e_ls); if (pi->edge_last == NULL) { pi->edge_last = eed; } } } } BLI_freelistN(&isect_lb); BLI_ghash_free(isect_hash, NULL, NULL); { ScanFillEdge *e_init; ScanFillEdge *e_curr; ScanFillEdge *e_next; ScanFillVert *v_prev; ScanFillVert *v_curr; int inside = false; /* first vert */ #if 0 e_init = pi->edge_last; e_curr = e_init; e_next = pi->edge_first; v_prev = e_curr->v1; v_curr = e_curr->v2; #else /* find outside vertex */ { ScanFillEdge *eed; ScanFillEdge *eed_prev; float min_x = FLT_MAX; e_curr = pi->edge_last; e_next = pi->edge_first; eed_prev = pi->edge_last; for (eed = pi->edge_first; eed; eed = (eed == pi->edge_last) ? NULL : eed->next) { if (eed->v2->co[0] < min_x) { min_x = eed->v2->co[0]; e_curr = eed_prev; e_next = eed; } eed_prev = eed; } e_init = e_curr; v_prev = e_curr->v1; v_curr = e_curr->v2; } #endif BLI_assert(e_curr->poly_nr == poly_nr); BLI_assert(pi->edge_last->poly_nr == poly_nr); do { ScanFillVert *v_next; v_next = (e_next->v1 == v_curr) ? e_next->v2 : e_next->v1; BLI_assert(ELEM(v_curr, e_next->v1, e_next->v2)); /* track intersections */ if (inside) { EFLAG_SET(e_next, E_ISDELETE); } if (v_next->user_flag & V_ISISECT) { inside = !inside; } /* now step... */ v_prev = v_curr; v_curr = v_next; e_curr = e_next; e_next = edge_step(poly_info, poly_nr, v_prev, v_curr, e_curr); } while (e_curr != e_init); } return true; }