/** * Return a constraint that requires a region to satisfy both \p a and \p b. * * Moreover, any region satisfying \p a and \p b will also satisfy the returned * constraint. * * \return \c NULL if no solution could be found (note that \c NULL is a valid * PedConstraint). */ PedConstraint* ped_constraint_intersect (const PedConstraint* a, const PedConstraint* b) { PedAlignment* start_align; PedAlignment* end_align; PedGeometry* start_range; PedGeometry* end_range; PedSector min_size; PedSector max_size; PedConstraint* constraint; if (!a || !b) return NULL; start_align = ped_alignment_intersect (a->start_align, b->start_align); if (!start_align) goto empty; end_align = ped_alignment_intersect (a->end_align, b->end_align); if (!end_align) goto empty_destroy_start_align; start_range = ped_geometry_intersect (a->start_range, b->start_range); if (!start_range) goto empty_destroy_end_align; end_range = ped_geometry_intersect (a->end_range, b->end_range); if (!end_range) goto empty_destroy_start_range; min_size = PED_MAX (a->min_size, b->min_size); max_size = PED_MIN (a->max_size, b->max_size); constraint = ped_constraint_new ( start_align, end_align, start_range, end_range, min_size, max_size); if (!constraint) goto empty_destroy_end_range; ped_alignment_destroy (start_align); ped_alignment_destroy (end_align); ped_geometry_destroy (start_range); ped_geometry_destroy (end_range); return constraint; empty_destroy_end_range: ped_geometry_destroy (end_range); empty_destroy_start_range: ped_geometry_destroy (start_range); empty_destroy_end_align: ped_alignment_destroy (end_align); empty_destroy_start_align: ped_alignment_destroy (start_align); empty: return NULL; }
PyObject *py_ped_geometry_intersect(PyObject *s, PyObject *args) { PyObject *in_b = NULL; PedGeometry *out_a = NULL, *out_b = NULL, *geom = NULL; _ped_Geometry *ret = NULL; if (!PyArg_ParseTuple(args, "O!", &_ped_Geometry_Type_obj, &in_b)) { return NULL; } out_a = _ped_Geometry2PedGeometry(s); if (out_a == NULL) { return NULL; } out_b = _ped_Geometry2PedGeometry(in_b); if (out_b == NULL) { return NULL; } geom = ped_geometry_intersect (out_a, out_b); if (geom) { ret = PedGeometry2_ped_Geometry(geom); } else { if (partedExnRaised) { partedExnRaised = 0; if (!PyErr_ExceptionMatches(PartedException) && !PyErr_ExceptionMatches(PyExc_NotImplementedError)) PyErr_SetString(CreateException, partedExnMessage); } else PyErr_SetString(PyExc_ArithmeticError, "Could not find geometry intersection"); return NULL; } return (PyObject *) ret; }
/* * Given a constraint and a start ("half of the solution"), find the * range of all possible ends, such that all (start, end) are solutions * to constraint (subject to additional alignment requirements). */ static PedGeometry* _constraint_get_end_range (const PedConstraint* constraint, PedSector start) { PedDevice* dev = constraint->end_range->dev; PedSector first_min_max_end; PedSector last_min_max_end; PedGeometry end_min_max_range; if (start + constraint->min_size - 1 > dev->length - 1) return NULL; first_min_max_end = start + constraint->min_size - 1; last_min_max_end = start + constraint->max_size - 1; if (last_min_max_end > dev->length - 1) last_min_max_end = dev->length - 1; ped_geometry_init (&end_min_max_range, dev, first_min_max_end, last_min_max_end - first_min_max_end + 1); return ped_geometry_intersect (&end_min_max_range, constraint->end_range); }
/* * Return the region within which the start must lie * in order to satisfy a constriant. It takes into account * constraint->start_range, constraint->min_size and constraint->max_size. * All sectors in this range that also satisfy alignment requirements have * an end, such that the (start, end) satisfy the constraint. */ static PedGeometry* _constraint_get_canonical_start_range (const PedConstraint* constraint) { PedSector first_end_soln; PedSector last_end_soln; PedSector min_start; PedSector max_start; PedGeometry start_min_max_range; if (constraint->min_size > constraint->max_size) return NULL; first_end_soln = ped_alignment_align_down ( constraint->end_align, constraint->end_range, constraint->end_range->start); last_end_soln = ped_alignment_align_up ( constraint->end_align, constraint->end_range, constraint->end_range->end); if (first_end_soln == -1 || last_end_soln == -1 || first_end_soln > last_end_soln || last_end_soln < constraint->min_size) return NULL; min_start = first_end_soln - constraint->max_size + 1; if (min_start < 0) min_start = 0; max_start = last_end_soln - constraint->min_size + 1; if (max_start < 0) return NULL; ped_geometry_init ( &start_min_max_range, constraint->start_range->dev, min_start, max_start - min_start + 1); return ped_geometry_intersect (&start_min_max_range, constraint->start_range); }