#include "converter.h" #include "mpl_kind_code.h" #include <limits> namespace contourpy { void Converter::check_max_offset(count_t max_offset) { if (max_offset > std::numeric_limits<OffsetArray::value_type>::max()) throw std::range_error("Max offset too large to fit in np.uint32. Use smaller chunks."); } CodeArray Converter::convert_codes( count_t point_count, count_t cut_count, const offset_t* cut_start, offset_t subtract) { assert(point_count > 0 && cut_count > 0); assert(cut_start != nullptr); index_t codes_shape = static_cast<index_t>(point_count); CodeArray py_codes(codes_shape); convert_codes(point_count, cut_count, cut_start, subtract, py_codes.mutable_data()); return py_codes; } void Converter::convert_codes( count_t point_count, count_t cut_count, const offset_t* cut_start, offset_t subtract, CodeArray::value_type* codes) { assert(point_count > 0 && cut_count > 0); assert(cut_start != nullptr); assert(codes != nullptr); std::fill(codes + 1, codes + point_count - 1, LINETO); for (decltype(cut_count) i = 0; i < cut_count-1; ++i) { codes[cut_start[i] - subtract] = MOVETO; codes[cut_start[i+1] - 1 - subtract] = CLOSEPOLY; } } CodeArray Converter::convert_codes_check_closed( count_t point_count, count_t cut_count, const offset_t* cut_start, const double* points) { assert(point_count > 0 && cut_count > 0); assert(cut_start != nullptr); assert(points != nullptr); index_t codes_shape = static_cast<index_t>(point_count); CodeArray codes(codes_shape); convert_codes_check_closed(point_count, cut_count, cut_start, points, codes.mutable_data()); return codes; } void Converter::convert_codes_check_closed( count_t point_count, count_t cut_count, const offset_t* cut_start, const double* points, CodeArray::value_type* codes) { assert(point_count > 0 && cut_count > 0); assert(cut_start != nullptr); assert(points != nullptr); assert(codes != nullptr); std::fill(codes + 1, codes + point_count, LINETO); for (decltype(cut_count) i = 0; i < cut_count-1; ++i) { auto start = cut_start[i]; auto end = cut_start[i+1]; codes[start] = MOVETO; bool closed = points[2*start] == points[2*end-2] && points[2*start+1] == points[2*end-1]; if (closed) codes[end-1] = CLOSEPOLY; } } CodeArray Converter::convert_codes_check_closed_single( count_t point_count, const double* points) { assert(point_count > 0); assert(points != nullptr); index_t codes_shape = static_cast<index_t>(point_count); CodeArray py_codes(codes_shape); convert_codes_check_closed_single(point_count, points, py_codes.mutable_data()); return py_codes; } void Converter::convert_codes_check_closed_single( count_t point_count, const double* points, CodeArray::value_type* codes) { assert(point_count > 0); assert(points != nullptr); assert(codes != nullptr); codes[0] = MOVETO; auto start = points; auto end = points + 2*point_count; bool closed = *start == *(end-2) && *(start+1) == *(end-1); if (closed) { std::fill(codes + 1, codes + point_count - 1, LINETO); codes[point_count-1] = CLOSEPOLY; } else std::fill(codes + 1, codes + point_count, LINETO); } OffsetArray Converter::convert_offsets( count_t offset_count, const offset_t* start, offset_t subtract) { assert(offset_count > 0); assert(start != nullptr); index_t offsets_shape = static_cast<index_t>(offset_count); OffsetArray py_offsets(offsets_shape); convert_offsets(offset_count, start, subtract, py_offsets.mutable_data()); return py_offsets; } void Converter::convert_offsets( count_t offset_count, const offset_t* start, offset_t subtract, OffsetArray::value_type* offsets) { assert(offset_count > 0); assert(start != nullptr); assert(offsets != nullptr); check_max_offset(*(start + offset_count - 1) - subtract); if (subtract == 0) std::copy(start, start + offset_count, offsets); else { for (decltype(offset_count) i = 0; i < offset_count; ++i) *offsets++ = start[i] - subtract; } } PointArray Converter::convert_points(count_t point_count, const double* start) { assert(point_count > 0); assert(start != nullptr); index_t points_shape[2] = {static_cast<index_t>(point_count), 2}; PointArray py_points(points_shape); convert_points(point_count, start, py_points.mutable_data()); return py_points; } void Converter::convert_points(count_t point_count, const double* start, double* points) { assert(point_count > 0); assert(start != nullptr); assert(points != nullptr); std::copy(start, start + 2*point_count, points); } } // namespace contourpy