You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复polybool.dart差集运算中自相交多边形导致的孔洞问题?

问题:polybool.dart处理自相交多边形差集时出现孔洞

我需要让polybool.dart库支持自相交多边形处理,但目前对自相交多边形执行差集运算时,自相交位置会出现孔洞。左侧为差集运算后带孔洞的效果,右侧为原始多边形展示。

我已在GitHub提交该问题,该库移植自TypeScript版polybool,其算法基于一篇论文,论文提到仅需小修改即可支持自相交多边形,另有相关教程。

以下是安装该包后用于测试的Flutter项目最小示例代码:

import 'package:flutter/material.dart';
import 'package:polybool/polybool.dart';

/// This example shows two sets of polygons side-by-side.
///
/// On the LEFT:
///   - We compute shape1 - shape2 (the difference),
///
/// On the RIGHT:
///   - We simply show shape1 and shape2 as-is (no difference).
void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: SafeArea(child: ShowPolygonsSideBySide())),
    ),
  );
}

class ShowPolygonsSideBySide extends StatelessWidget {
  const ShowPolygonsSideBySide({super.key});

  @override
  Widget build(BuildContext context) {
    // Self-Intersecting Polygon
    final shape1poly = Polygon(
      regions: [
        [
          Coordinate(100, 600),
          Coordinate(200, 600),
          Coordinate(200, 900),
          Coordinate(50, 900),
          Coordinate(50, 700),
          Coordinate(300, 700),
          Coordinate(300, 650),
          Coordinate(5, 650),
          Coordinate(5, 1000),
          Coordinate(250, 1000),
          Coordinate(250, 500),
          Coordinate(100, 500),
        ],
      ],
    );
    // Simple Polygon for subtraction
    final shape2poly = Polygon(
      regions: [
        [
          Coordinate(50, 520),
          Coordinate(350, 520),
          Coordinate(350, 560),
          Coordinate(50, 560),
        ],
      ],
    );

    // ------------------------------------------
    // Shifting ONLY for better on-screen viewing
    // !!NOT NECESSARY FOR THE ACTUAL PROLBEM!!
    // ------------------------------------------
    final leftShape1 = _shiftPolygon(shape1poly, 50, -400);
    final leftShape2 = _shiftPolygon(shape2poly, 50, -400);
    final rightShape1 = _shiftPolygon(leftShape1, 400, 0);
    final rightShape2 = _shiftPolygon(leftShape2, 400, 0);

    // Build the difference (shape1 - shape2)
    final differenceLeft = leftShape1.difference(leftShape2);

    return CustomPaint(
      painter: FourPolygonsPainter(
        differenceLeft: differenceLeft,
        leftShape2: leftShape2,
        // Right side: original shapes (no difference)
        rightShape1: rightShape1,
        rightShape2: rightShape2,
      ),
      child: const SizedBox.expand(),
    );
  }

  /// Utility to shift every coordinate of a Polygon by [dx], [dy].
  /// This is only for better on-screen viewing!!
  Polygon _shiftPolygon(Polygon source, double dx, double dy) {
    final newRegions = <List<Coordinate>>[];
    for (final region in source.regions) {
      final shiftedRegion = <Coordinate>[];
      for (final c in region) {
        shiftedRegion.add(Coordinate(c.x + dx, c.y + dy));
      }
      newRegions.add(shiftedRegion);
    }
    return Polygon(regions: newRegions);
  }
}

class FourPolygonsPainter extends CustomPainter {
  final Polygon differenceLeft;
  final Polygon leftShape2;
  final Polygon rightShape1;
  final Polygon rightShape2;

  FourPolygonsPainter({
    required this.differenceLeft,
    required this.leftShape2,
    required this.rightShape1,
    required this.rightShape2,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // LEFT SIDE:
    // The difference (shape1 - shape2) in black
    _drawPolygon(canvas, differenceLeft, Colors.black);

    // RIGHT SIDE:
    // Showcase of the raw Polygons (no difference)
    _drawPolygon(canvas, rightShape1, Colors.black);
    _drawPolygon(canvas, rightShape2, Colors.red);
  }

  @override
  bool shouldRepaint(FourPolygonsPainter oldDelegate) => false;

  /// Draws all regions of a [Polygon].
  void _drawPolygon(Canvas canvas, Polygon polygon, Color color) {
    final paint = Paint()..color = color;

    for (final region in polygon.regions) {
      if (region.isEmpty) continue;
      final path = Path()..moveTo(region.first.x, region.first.y);
      for (int i = 1; i < region.length; i++) {
        path.lineTo(region[i].x, region[i].y);
      }
      path.close();
      canvas.drawPath(path, paint);
    }
  }
}

尽管有这些资料,我仍无法解决该问题,希望获得帮助以改进该Dart库,使其支持自相交多边形处理。


内容的提问来源于stack exchange,提问作者Jan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:47:03