123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- #include "base_impl.h"
- #include "converter.h"
- #include "serial.h"
- namespace contourpy {
- SerialContourGenerator::SerialContourGenerator(
- const CoordinateArray& x, const CoordinateArray& y, const CoordinateArray& z,
- const MaskArray& mask, bool corner_mask, LineType line_type, FillType fill_type,
- bool quad_as_tri, ZInterp z_interp, index_t x_chunk_size, index_t y_chunk_size)
- : BaseContourGenerator(x, y, z, mask, corner_mask, line_type, fill_type, quad_as_tri, z_interp,
- x_chunk_size, y_chunk_size)
- {}
- void SerialContourGenerator::export_filled(
- const ChunkLocal& local, std::vector<py::list>& return_lists)
- {
- assert(local.total_point_count > 0);
- switch (get_fill_type())
- {
- case FillType::OuterCode:
- case FillType::OuterOffset: {
- assert(!has_direct_points() && !has_direct_line_offsets());
- auto outer_count = local.line_count - local.hole_count;
- for (decltype(outer_count) i = 0; i < outer_count; ++i) {
- auto outer_start = local.outer_offsets.start[i];
- auto outer_end = local.outer_offsets.start[i+1];
- auto point_start = local.line_offsets.start[outer_start];
- auto point_end = local.line_offsets.start[outer_end];
- auto point_count = point_end - point_start;
- assert(point_count > 2);
- return_lists[0].append(Converter::convert_points(
- point_count, local.points.start + 2*point_start));
- if (get_fill_type() == FillType::OuterCode)
- return_lists[1].append(Converter::convert_codes(
- point_count, outer_end - outer_start + 1,
- local.line_offsets.start + outer_start, point_start));
- else
- return_lists[1].append(Converter::convert_offsets(
- outer_end - outer_start + 1, local.line_offsets.start + outer_start,
- point_start));
- }
- break;
- }
- case FillType::ChunkCombinedCode:
- case FillType::ChunkCombinedCodeOffset: {
- assert(has_direct_points() && !has_direct_line_offsets());
- // return_lists[0][local_chunk] already contains combined points.
- // If ChunkCombinedCodeOffset. return_lists[2][local.chunk] already contains outer
- // offsets.
- return_lists[1][local.chunk] = Converter::convert_codes(
- local.total_point_count, local.line_count + 1, local.line_offsets.start, 0);
- break;
- }
- case FillType::ChunkCombinedOffset:
- case FillType::ChunkCombinedOffsetOffset:
- assert(has_direct_points() && has_direct_line_offsets());
- if (get_fill_type() == FillType::ChunkCombinedOffsetOffset) {
- assert(has_direct_outer_offsets());
- }
- // return_lists[0][local_chunk] already contains combined points.
- // return_lists[1][local.chunk] already contains line offsets.
- // If ChunkCombinedOffsetOffset, return_lists[2][local.chunk] already contains
- // outer offsets.
- break;
- }
- }
- void SerialContourGenerator::export_lines(
- const ChunkLocal& local, std::vector<py::list>& return_lists)
- {
- assert(local.total_point_count > 0);
- switch (get_line_type())
- {
- case LineType::Separate:
- case LineType::SeparateCode: {
- assert(!has_direct_points() && !has_direct_line_offsets());
- bool separate_code = (get_line_type() == LineType::SeparateCode);
- for (decltype(local.line_count) i = 0; i < local.line_count; ++i) {
- auto point_start = local.line_offsets.start[i];
- auto point_end = local.line_offsets.start[i+1];
- auto point_count = point_end - point_start;
- assert(point_count > 1);
- return_lists[0].append(Converter::convert_points(
- point_count, local.points.start + 2*point_start));
- if (separate_code) {
- return_lists[1].append(
- Converter::convert_codes_check_closed_single(
- point_count, local.points.start + 2*point_start));
- }
- }
- break;
- }
- case LineType::ChunkCombinedCode: {
- assert(has_direct_points() && !has_direct_line_offsets());
- // return_lists[0][local.chunk] already contains points.
- return_lists[1][local.chunk] = Converter::convert_codes_check_closed(
- local.total_point_count, local.line_count + 1, local.line_offsets.start,
- local.points.start);
- break;
- }
- case LineType::ChunkCombinedOffset:
- assert(has_direct_points() && has_direct_line_offsets());
- // return_lists[0][local.chunk] already contains points.
- // return_lists[1][local.chunk] already contains line offsets.
- break;
- case LineType::ChunkCombinedNan:
- assert(has_direct_points());
- // return_lists[0][local.chunk] already contains points.
- break;
- }
- }
- void SerialContourGenerator::march(std::vector<py::list>& return_lists)
- {
- auto n_chunks = get_n_chunks();
- bool single_chunk = (n_chunks == 1);
- if (single_chunk) {
- // Stage 1: If single chunk, initialise cache z-levels and starting locations for whole
- // domain.
- init_cache_levels_and_starts();
- }
- // Stage 2: Trace contours.
- ChunkLocal local;
- for (index_t chunk = 0; chunk < n_chunks; ++chunk) {
- get_chunk_limits(chunk, local);
- if (!single_chunk)
- init_cache_levels_and_starts(&local);
- march_chunk(local, return_lists);
- local.clear();
- }
- }
- } // namespace contourpy
|