[Bf-blender-cvs] [87d5bd5fb06] temp-gpencil-bezier-stroke-type: GPencil: Implement Merge by Distance for curves
Falk David
noreply at git.blender.org
Wed May 5 14:43:09 CEST 2021
Commit: 87d5bd5fb06340ecfd543518490e6278a9b83ee0
Author: Falk David
Date: Wed May 5 14:42:56 2021 +0200
Branches: temp-gpencil-bezier-stroke-type
https://developer.blender.org/rB87d5bd5fb06340ecfd543518490e6278a9b83ee0
GPencil: Implement Merge by Distance for curves
This commit adds the `BKE_gpencil_editcurve_merge_distance` function.
It will merge the control points by distance (always at the first point).
===================================================================
M source/blender/blenkernel/BKE_gpencil_curve.h
M source/blender/blenkernel/intern/gpencil_curve.c
M source/blender/editors/gpencil/gpencil_edit.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h
index e213cf7a4c5..bc3f8208ac3 100644
--- a/source/blender/blenkernel/BKE_gpencil_curve.h
+++ b/source/blender/blenkernel/BKE_gpencil_curve.h
@@ -87,6 +87,11 @@ void BKE_gpencil_editcurve_smooth(struct bGPDstroke *gps,
const bool do_positions,
const bool do_pressure,
const bool do_strength);
+bool BKE_gpencil_editcurve_merge_distance(struct bGPDstroke *gps,
+ const float threshold,
+ const bool use_unselected,
+ const bool refit_segments,
+ const float error_threshold);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index 858e09034b8..5a32b135b42 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -2341,4 +2341,70 @@ void BKE_gpencil_editcurve_smooth(bGPDstroke *gps,
}
}
+/**
+ * Curve Merge by Distance
+ * Merge the control points by distance. Merging will always occur on the first point.
+ * The first and last point are never merged. Note: The caller is resposible for the geometry
+ * update of the stroke.
+ * \param gps: Grease Pencil stroke.
+ * \param threshold: Distance between points.
+ * \param use_unselected: Set to true to analyze all stroke and not only selected points.
+ * \param refit_segments: Set to refit segments where points were dissolved.
+ * \param error_threshold: Error threshold for refitting (only used when refit_segments = true).
+ * \returns True if any point was merged and the geometry changed.
+ */
+bool BKE_gpencil_editcurve_merge_distance(bGPDstroke *gps,
+ const float threshold,
+ const bool use_unselected,
+ const bool refit_segments,
+ const float error_threshold)
+{
+ bGPDcurve *gpc = gps->editcurve;
+ if (gpc == NULL || gpc->tot_curve_points < 2 || threshold == 0.0f) {
+ return false;
+ }
+ const float th_square = threshold * threshold;
+
+ bool tagged = false;
+ int i = 0, step = 1;
+ while ((i < gpc->tot_curve_points - 1) && (i + step < gpc->tot_curve_points)) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+ bGPDcurve_point *gpc_pt_next = &gpc->curve_points[i + step];
+ if ((!use_unselected && ((gpc_pt->flag & GP_CURVE_POINT_SELECT) == 0 ||
+ (gpc_pt_next->flag & GP_CURVE_POINT_SELECT) == 0)) ||
+ (gpc_pt->flag & GP_CURVE_POINT_TAG)) {
+ i++;
+ step = 1;
+ continue;
+ }
+ if (gpc_pt_next->flag & GP_CURVE_POINT_TAG) {
+ step++;
+ continue;
+ }
+ BezTriple *bezt = &gpc_pt->bezt;
+ BezTriple *bezt_next = &gpc_pt_next->bezt;
+
+ float len_square = len_squared_v3v3(bezt->vec[1], bezt_next->vec[1]);
+ if (len_square <= th_square) {
+ gpc_pt_next->flag |= GP_CURVE_POINT_TAG;
+ tagged = true;
+ step++;
+ }
+ else {
+ i++;
+ step = 1;
+ }
+ }
+
+ gpc->curve_points[0].flag &= ~GP_CURVE_POINT_TAG;
+ gpc->curve_points[gpc->tot_curve_points - 1].flag &= ~GP_CURVE_POINT_TAG;
+
+ int old_num_points = gpc->tot_curve_points;
+ if (tagged) {
+ return BKE_gpencil_editcurve_dissolve(
+ gps, GP_CURVE_POINT_TAG, refit_segments, error_threshold) != old_num_points;
+ }
+ return false;
+}
+
/** \} */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 2299a1a42f4..c90d255c413 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -5624,24 +5624,31 @@ static int gpencil_merge_by_distance_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
-
- if (is_curve_edit) {
- /* TODO: merge curve points by distance */
- }
- else {
- /* Go through each editable selected stroke */
- GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
- if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_stroke_merge_distance(gpd, gpf_, gps, threshold, unselected);
+ bool changed = false;
+ /* Go through each editable selected stroke */
+ GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ if (GPENCIL_STROKE_TYPE_BEZIER(gps)) {
+ bGPDcurve *gpc = gps->editcurve;
+ if (gpc->flag & GP_CURVE_SELECT) {
+ /* TODO: don't hardcode the refit and threshold. Figure out how to set these. */
+ if (BKE_gpencil_editcurve_merge_distance(gps, threshold, unselected, false, 0.0f)) {
+ BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT);
+ changed = true;
+ }
}
}
- GP_EDITABLE_STROKES_END(gpstroke_iter);
+ else if (gps->flag & GP_STROKE_SELECT) {
+ BKE_gpencil_stroke_merge_distance(gpd, gpf_, gps, threshold, unselected);
+ changed = true;
+ }
}
+ GP_EDITABLE_STROKES_END(gpstroke_iter);
- /* notifiers */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ if (changed) {
+ /* notifiers */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
return OPERATOR_FINISHED;
}
More information about the Bf-blender-cvs
mailing list