diff --git a/src/GivRenderer.cc b/src/GivRenderer.cc index 9965faf..ddde48c 100644 --- a/src/GivRenderer.cc +++ b/src/GivRenderer.cc @@ -51,13 +51,14 @@ static void print_polygon(const Polygon& poly) print("}}\n"); } // Apply the clipping algorithm and add the given polygon -void GivRenderer::add_clipped_poly(const Polygon& poly) +void GivRenderer::add_clipped_poly(const Polygon& poly, + bool is_closed) { int n = (int)poly.size(); if (n<2) return; - Polygon clip = poly_clip(poly, clip_rect); + Polygon clip = poly_clip(poly, clip_rect, is_closed); #if 0 print("input_poly: "); print_polygon(poly); print("clip_poly: "); print_polygon(clip_rect); @@ -167,7 +168,7 @@ void GivRenderer::paint() last_move_to_y = m_y; if (i<2 && p.op == Op::OP_MOVE) { - add_clipped_poly(poly); + add_clipped_poly(poly, false); poly.clear(); painter.new_path(); poly.push_back({m_x,m_y}); @@ -236,7 +237,7 @@ void GivRenderer::paint() double margin = line_width * 20; build_clip_rect(margin); - add_clipped_poly(poly); + add_clipped_poly(poly, true); painter.close_path(); poly.clear(); } @@ -245,7 +246,7 @@ void GivRenderer::paint() } if (i<2) { // draw polygon - add_clipped_poly(poly); + add_clipped_poly(poly, true); if (i==0) painter.fill(); } diff --git a/src/GivRenderer.h b/src/GivRenderer.h index 38a4a04..ea93d74 100644 --- a/src/GivRenderer.h +++ b/src/GivRenderer.h @@ -24,7 +24,7 @@ class GivRenderer { } private: - void add_clipped_poly(const sutherland_hodgeman_polygon_clipping::Polygon& poly); + void add_clipped_poly(const sutherland_hodgeman_polygon_clipping::Polygon& poly, bool is_closed); void build_clip_rect(double margin); diff --git a/src/SutherlandHodgmanPolygonClipping.cc b/src/SutherlandHodgmanPolygonClipping.cc index 00dcb75..f3ad8dd 100644 --- a/src/SutherlandHodgmanPolygonClipping.cc +++ b/src/SutherlandHodgmanPolygonClipping.cc @@ -8,6 +8,7 @@ #include #include "SutherlandHodgmanPolygonClipping.h" #include +#include using namespace std; using namespace fmt; @@ -64,6 +65,11 @@ static bool is_inside_edge(const vec2& q, const vec2pair& edge) <=0); } +#if 0 + +// This is not needed after fixing the poly_clip to exclude +// the last to first point (and thus work with polylines) +// // Check if the candidate point is colinear with the edge. // The "epsilon" is totally heuristic. // @@ -87,17 +93,68 @@ static bool contained_by(const vec2pair& candidate, const vec2pair& edge) // What other heuristics? Perhaps touches edge? return true; } +#endif + +#if 0 +// For debugging the clipping algo +int Counter = 0; +void save_algo_snapshot(const Polygon& path, + const Polygon& rect_clip_path, + const Polygon& in_list, + const Polygon& out_list, + const vec2pair& clip_edge + ) +{ + auto filename = format("/tmp/shpc-{:03d}.giv", Counter++); + print("Saving to {}\n", filename); + ofstream fh(filename); + fh << format("$path path\n" + "$color pink\n"); + for (const auto& p: path) + fh << format("{} {}\n", p.x, p.y); + + fh << format("\n$path clip_edge\n" + "$color red\n" + "$lw 2\n" + ); + fh << format("{} {}\n", clip_edge.p0.x, clip_edge.p0.y); + fh << format("{} {}\n", clip_edge.p1.x, clip_edge.p1.y); + + + + fh << format("\n" + "$path rect_clip\n" + "$color green\n"); + for (const auto& p: rect_clip_path) + fh << format("{} {}\n", p.x, p.y); + fh << "z\n"; + + fh << format("\n" + "$path in_list\n" + "$color purple\n"); + for (const auto& p: in_list) + fh << format("{} {}\n", p.x, p.y); + + fh << format("\n" + "$path out_list\n" + "$color blue\n"); + for (const auto& p: out_list) + fh << format("{} {}\n", p.x, p.y); + +} +#endif - -// Sutherland Hodgman Polygon clipping algorithm. The disadvantage -// of this algorithm is that it does not distinguish between -// an edge between the last and the first segment of the path -// vs a real edge. This is hackishly taken care of in an -// additional sweep that rotates the path so that it the -// last to the first point occur at the end of the clipped path. +// Sutherland Hodgman Polygon clipping algorithm modified to +// work with either polylines or polygons depending on the +// is_closed parameter. Polygon poly_clip(const Polygon& path, - const Polygon& rect_clip_path) + const Polygon& rect_clip_path, + bool is_closed) { +#if 0 + print("-----\n"); + Counter = 0; +#endif Polygon out_list = path; int m = (int)rect_clip_path.size(); @@ -111,25 +168,39 @@ Polygon poly_clip(const Polygon& path, for (int j=0; j0; const vec2& prev_point = in_list[(j + n - 1) % n]; const vec2& current_point = in_list[j]; if (is_inside_edge(current_point, clip_edge)) { - if (!is_inside_edge(prev_point, clip_edge)) + if (!is_inside_edge(prev_point, clip_edge) + && draw_prev + ) out_list.push_back(compute_intersection( {prev_point, current_point}, clip_edge)); out_list.push_back(current_point); } - else if (is_inside_edge(prev_point, clip_edge)) + else if (is_inside_edge(prev_point, clip_edge) + && draw_prev + ) out_list.push_back(compute_intersection( {prev_point, current_point}, clip_edge)); } + // save_algo_snapshot(path, rect_clip_path, in_list, out_list, clip_edge); } +#if 0 // Sweep through list looking for a pair that is contained by // the first to last point, and rotate the list to put // it at the end. + // + // This was done before I realized that I can get the same result + // much faster by using draw_prev vec2pair first_last {path.back(), path[0]}; int n = (int)out_list.size(); for (int i=0; i<(int)out_list.size(); i++) @@ -145,6 +216,7 @@ Polygon poly_clip(const Polygon& path, break; } } +#endif return out_list; } diff --git a/src/SutherlandHodgmanPolygonClipping.h b/src/SutherlandHodgmanPolygonClipping.h index 6f28b8a..3e8eda7 100644 --- a/src/SutherlandHodgmanPolygonClipping.h +++ b/src/SutherlandHodgmanPolygonClipping.h @@ -25,7 +25,8 @@ struct vec2pair { using Polygon = std::vector; Polygon poly_clip(const Polygon& path, - const Polygon& rect_clip_path); + const Polygon& rect_clip_path, + bool is_closed); } #endif diff --git a/src/plugins/simple_dicom.c b/src/plugins/simple_dicom.c index 55f2bfb..64de651 100644 --- a/src/plugins/simple_dicom.c +++ b/src/plugins/simple_dicom.c @@ -27,10 +27,11 @@ gboolean giv_plugin_supports_file(const char *filename, guchar *start_chunk, gint start_chunk_len) { - gboolean is_dicom = g_ascii_strncasecmp ((gchar*)start_chunk+0x80, - "DICM",4) == 0; - - return is_dicom; + if (start_chunk) + return = g_ascii_strncasecmp ((gchar*)start_chunk+0x80, + "DICM",4) == 0; + return g_ascii_strncasecmp((gchar*)filename+strlen(filename)-4, + ".dcm",4)==0; } GivImage *giv_plugin_load_file(const char *filename,