|
22 | 22 |
|
23 | 23 | // ImPlot v0.17 |
24 | 24 |
|
| 25 | +#ifndef IMGUI_DEFINE_MATH_OPERATORS |
25 | 26 | #define IMGUI_DEFINE_MATH_OPERATORS |
| 27 | +#endif |
26 | 28 | #include "implot.h" |
| 29 | +#ifndef IMGUI_DISABLE |
27 | 30 | #include "implot_internal.h" |
28 | 31 |
|
29 | 32 | //----------------------------------------------------------------------------- |
@@ -2197,20 +2200,53 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() |
2197 | 2200 | // [SECTION] PlotPieChart |
2198 | 2201 | //----------------------------------------------------------------------------- |
2199 | 2202 |
|
2200 | | -IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col) { |
| 2203 | +IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col, bool detached = false) { |
2201 | 2204 | const float resolution = 50 / (2 * IM_PI); |
2202 | 2205 | ImVec2 buffer[52]; |
2203 | | - buffer[0] = PlotToPixels(center,IMPLOT_AUTO,IMPLOT_AUTO); |
| 2206 | + |
2204 | 2207 | int n = ImMax(3, (int)((a1 - a0) * resolution)); |
2205 | 2208 | double da = (a1 - a0) / (n - 1); |
2206 | 2209 | int i = 0; |
2207 | | - for (; i < n; ++i) { |
2208 | | - double a = a0 + i * da; |
2209 | | - buffer[i + 1] = PlotToPixels(center.x + radius * cos(a), center.y + radius * sin(a),IMPLOT_AUTO,IMPLOT_AUTO); |
2210 | | - } |
2211 | | - buffer[i+1] = buffer[0]; |
| 2210 | + |
| 2211 | + if (detached) { |
| 2212 | + const double offset = 0.08; // Offset of the detached slice |
| 2213 | + const double width_scale = 0.95; // Scale factor for the width of the detached slice |
| 2214 | + |
| 2215 | + double a_mid = (a0 + a1) / 2; |
| 2216 | + double new_a0 = a_mid - (a1 - a0) * width_scale / 2; |
| 2217 | + double new_a1 = a_mid + (a1 - a0) * width_scale / 2; |
| 2218 | + double new_da = (new_a1 - new_a0) / (n - 1); |
| 2219 | + |
| 2220 | + ImPlotPoint offsetCenter(center.x + offset * cos(a_mid), center.y + offset * sin(a_mid)); |
| 2221 | + |
| 2222 | + // Start point (center of the offset) |
| 2223 | + buffer[0] = PlotToPixels(offsetCenter, IMPLOT_AUTO, IMPLOT_AUTO); |
| 2224 | + |
| 2225 | + for (; i < n; ++i) { |
| 2226 | + double a = new_a0 + i * new_da; |
| 2227 | + buffer[i + 1] = PlotToPixels( |
| 2228 | + offsetCenter.x + (radius + offset/2) * cos(a), |
| 2229 | + offsetCenter.y + (radius + offset/2) * sin(a), |
| 2230 | + IMPLOT_AUTO, IMPLOT_AUTO |
| 2231 | + ); |
| 2232 | + } |
| 2233 | + |
| 2234 | + } else { |
| 2235 | + buffer[0] = PlotToPixels(center, IMPLOT_AUTO, IMPLOT_AUTO); |
| 2236 | + for (; i < n; ++i) { |
| 2237 | + double a = a0 + i * da; |
| 2238 | + buffer[i + 1] = PlotToPixels( |
| 2239 | + center.x + radius * cos(a), |
| 2240 | + center.y + radius * sin(a), |
| 2241 | + IMPLOT_AUTO, IMPLOT_AUTO); |
| 2242 | + } |
| 2243 | + } |
| 2244 | + // Close the shape |
| 2245 | + buffer[i + 1] = buffer[0]; |
| 2246 | + |
2212 | 2247 | // fill |
2213 | | - draw_list.AddConvexPolyFilled(buffer, n + 1, col); |
| 2248 | + draw_list.AddConvexPolyFilled(buffer, n + 2, col); |
| 2249 | + |
2214 | 2250 | // border (for AA) |
2215 | 2251 | draw_list.AddPolyline(buffer, n + 2, col, 0, 2.0f); |
2216 | 2252 | } |
@@ -2254,21 +2290,21 @@ void PlotPieChartEx(const char* const label_ids[], const T* values, int count, I |
2254 | 2290 | ImPlotPoint Pmax = ImPlotPoint(center.x + radius, center.y + radius); |
2255 | 2291 | for (int i = 0; i < count; ++i) { |
2256 | 2292 | ImPlotItem* item = GetItem(label_ids[i]); |
2257 | | - |
2258 | 2293 | const double percent = normalize ? (double)values[i] / sum : (double)values[i]; |
2259 | 2294 | const bool skip = sum <= 0.0 || (ignore_hidden && item != nullptr && !item->Show); |
2260 | 2295 | if (!skip) |
2261 | 2296 | a1 = a0 + 2 * IM_PI * percent; |
2262 | 2297 |
|
2263 | 2298 | if (BeginItemEx(label_ids[i], FitterRect(Pmin, Pmax))) { |
| 2299 | + const bool hovered = ImPlot::IsLegendEntryHovered(label_ids[i]) && ImHasFlag(flags, ImPlotPieChartFlags_Exploding); |
2264 | 2300 | if (sum > 0.0) { |
2265 | 2301 | ImU32 col = GetCurrentItem()->Color; |
2266 | 2302 | if (percent < 0.5) { |
2267 | | - RenderPieSlice(draw_list, center, radius, a0, a1, col); |
| 2303 | + RenderPieSlice(draw_list, center, radius, a0, a1, col, hovered); |
2268 | 2304 | } |
2269 | 2305 | else { |
2270 | | - RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col); |
2271 | | - RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col); |
| 2306 | + RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col, hovered); |
| 2307 | + RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col, hovered); |
2272 | 2308 | } |
2273 | 2309 | } |
2274 | 2310 | EndItem(); |
@@ -2320,7 +2356,9 @@ void PlotPieChart(const char* const label_ids[], const T* values, int count, dou |
2320 | 2356 | fmt((double)values[i], buffer, 32, fmt_data); |
2321 | 2357 | ImVec2 size = ImGui::CalcTextSize(buffer); |
2322 | 2358 | double angle = a0 + (a1 - a0) * 0.5; |
2323 | | - ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle), IMPLOT_AUTO, IMPLOT_AUTO); |
| 2359 | + const bool hovered = ImPlot::IsLegendEntryHovered(label_ids[i]) && ImHasFlag(flags, ImPlotPieChartFlags_Exploding); |
| 2360 | + const double offset = (hovered ? 0.6 : 0.5) * radius; |
| 2361 | + ImVec2 pos = PlotToPixels(center.x + offset * cos(angle), center.y + offset * sin(angle), IMPLOT_AUTO, IMPLOT_AUTO); |
2324 | 2362 | ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color)); |
2325 | 2363 | draw_list.AddText(pos - size * 0.5f, col, buffer); |
2326 | 2364 | } |
@@ -2806,3 +2844,5 @@ void PlotDummy(const char* label_id, ImPlotDummyFlags flags) { |
2806 | 2844 | } |
2807 | 2845 |
|
2808 | 2846 | } // namespace ImPlot |
| 2847 | + |
| 2848 | +#endif // #ifndef IMGUI_DISABLE |
0 commit comments