|
@@ -0,0 +1,240 @@
|
|
|
+import 'dart:math' as math;
|
|
|
+import 'package:fis_common/logger/logger.dart';
|
|
|
+import 'package:fis_measure/vid.dart';
|
|
|
+
|
|
|
+import 'size.dart';
|
|
|
+
|
|
|
+class DRect {
|
|
|
+ static final DRect empty = DRect(
|
|
|
+ double.infinity,
|
|
|
+ double.infinity,
|
|
|
+ double.negativeInfinity,
|
|
|
+ double.negativeInfinity,
|
|
|
+ );
|
|
|
+
|
|
|
+ late double _x;
|
|
|
+ late double _y;
|
|
|
+ late double _width;
|
|
|
+ late double _height;
|
|
|
+
|
|
|
+ bool get isEmpty => _width < 0;
|
|
|
+
|
|
|
+ double get x => _x;
|
|
|
+ set x(double value) {
|
|
|
+ if (isEmpty) {
|
|
|
+ throw UnsupportedError("Rect_CannotModifyEmptyRect");
|
|
|
+ }
|
|
|
+ _x = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ double get y => _y;
|
|
|
+ set y(double value) {
|
|
|
+ if (isEmpty) {
|
|
|
+ throw UnsupportedError("Rect_CannotModifyEmptyRect");
|
|
|
+ }
|
|
|
+ _y = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ double get width => _width;
|
|
|
+ set width(double value) {
|
|
|
+ if (isEmpty) {
|
|
|
+ throw UnsupportedError("Rect_CannotModifyEmptyRect");
|
|
|
+ }
|
|
|
+ if (value < 0.0) {
|
|
|
+ throw ArgumentError("Size_WidthCannotBeNegative");
|
|
|
+ }
|
|
|
+ _width = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ double get height => _height;
|
|
|
+ set height(double value) {
|
|
|
+ if (isEmpty) {
|
|
|
+ throw UnsupportedError("Rect_CannotModifyEmptyRect");
|
|
|
+ }
|
|
|
+ if (value < 0.0) {
|
|
|
+ throw ArgumentError("Size_HeightCannotBeNegative");
|
|
|
+ }
|
|
|
+ _height = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ double get top => _y;
|
|
|
+ double get left => _x;
|
|
|
+
|
|
|
+ double get right {
|
|
|
+ if (isEmpty) {
|
|
|
+ return double.negativeInfinity;
|
|
|
+ }
|
|
|
+ return (_x + _width);
|
|
|
+ }
|
|
|
+
|
|
|
+ double get bottom {
|
|
|
+ if (isEmpty) {
|
|
|
+ return double.negativeInfinity;
|
|
|
+ }
|
|
|
+ return (_y + height);
|
|
|
+ }
|
|
|
+
|
|
|
+ DRect(double x, double y, double width, double height) {
|
|
|
+ if ((width < 0.0) || (height < 0.0)) {
|
|
|
+ logger.e("Size_WidthAndHeightCannotBeNegative($x,$y,$width,$height)");
|
|
|
+ width = height = 0;
|
|
|
+ }
|
|
|
+ _x = x;
|
|
|
+ _y = y;
|
|
|
+ _width = width;
|
|
|
+ _height = height;
|
|
|
+ }
|
|
|
+
|
|
|
+ factory DRect.fromSize(DSize size) {
|
|
|
+ if (size.isEmpty) return empty;
|
|
|
+ return DRect(0, 0, size.width, size.height);
|
|
|
+ }
|
|
|
+
|
|
|
+ factory DRect.fromPositionedSize(DPoint point, DSize size) {
|
|
|
+ return DRect(point.x, 0, point.y, size.height);
|
|
|
+ }
|
|
|
+
|
|
|
+ factory DRect.fromCrossPoints(DPoint p1, DPoint p2) {
|
|
|
+ final x = math.min(p1.x, p2.x);
|
|
|
+ final y = math.min(p1.y, p2.y);
|
|
|
+ final width = math.max((math.max(p1.x, p2.x) - x), 0.0);
|
|
|
+ final height = math.max((math.max(p1.y, p2.y) - y), 0.0);
|
|
|
+ return DRect(x, y, width, height);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool containsOffset(double x, double y) {
|
|
|
+ if (isEmpty) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return _containsOffsetInner(x, y);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool containsPoint(DPoint point) => containsOffset(point.x, point.y);
|
|
|
+ bool contains(DRect rect) {
|
|
|
+ if (isEmpty || rect.isEmpty) return false;
|
|
|
+ return ((x <= rect.x && y <= rect.y) &&
|
|
|
+ ((x + width) >= (rect._x + rect._width))) &&
|
|
|
+ ((y + height) >= (rect._y + rect._height));
|
|
|
+ }
|
|
|
+
|
|
|
+ bool intersectsWith(DRect rect) {
|
|
|
+ if (isEmpty || rect.isEmpty) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return ((((rect.left <= right) && (rect.right >= left)) &&
|
|
|
+ (rect.top <= bottom)) &&
|
|
|
+ (rect.bottom >= top));
|
|
|
+ }
|
|
|
+
|
|
|
+ void intersect(DRect rect) {
|
|
|
+ if (!intersectsWith(rect)) {
|
|
|
+ copyFrom(empty);
|
|
|
+ } else {
|
|
|
+ double num = math.max(left, rect.left);
|
|
|
+ double num2 = math.max(top, rect.top);
|
|
|
+ _width = math.max((math.min(right, rect.right) - num), 0.0);
|
|
|
+ _height = math.max((math.min(bottom, rect.bottom) - num2), 0.0);
|
|
|
+ _x = num;
|
|
|
+ _y = num2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void union(DRect rect) {
|
|
|
+ if (isEmpty) {
|
|
|
+ copyFrom(rect);
|
|
|
+ } else if (!rect.isEmpty) {
|
|
|
+ double num = math.min(left, rect.left);
|
|
|
+ double num2 = math.min(top, rect.top);
|
|
|
+ if ((rect.width == double.infinity) || (width == double.infinity)) {
|
|
|
+ _width = double.infinity;
|
|
|
+ } else {
|
|
|
+ double num3 = math.max(right, rect.right);
|
|
|
+ _width = math.max((num3 - num), 0.0);
|
|
|
+ }
|
|
|
+ if ((rect.height == double.infinity) || (height == double.infinity)) {
|
|
|
+ _height = double.infinity;
|
|
|
+ } else {
|
|
|
+ double num4 = math.max(bottom, rect.bottom);
|
|
|
+ _height = math.max((num4 - num2), 0.0);
|
|
|
+ }
|
|
|
+ _x = num;
|
|
|
+ _y = num2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void addOffset(double offsetX, double offsetY) {
|
|
|
+ if (isEmpty) {
|
|
|
+ throw UnsupportedError(("Rect_CannotCallMethod"));
|
|
|
+ }
|
|
|
+ _x += offsetX;
|
|
|
+ _y += offsetY;
|
|
|
+ }
|
|
|
+
|
|
|
+ void inflate(double width, double height) {
|
|
|
+ if (isEmpty) {
|
|
|
+ throw UnsupportedError(("Rect_CannotCallMethod"));
|
|
|
+ }
|
|
|
+ _x -= width;
|
|
|
+ _y -= height;
|
|
|
+ _width += width;
|
|
|
+ _width += width;
|
|
|
+ _height += height;
|
|
|
+ _height += height;
|
|
|
+ if ((_width < 0.0) || (_height < 0.0)) {
|
|
|
+ copyFrom(empty);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ static DRect parse(String source) {
|
|
|
+ DRect rect;
|
|
|
+ if (source == "Empty") {
|
|
|
+ rect = empty;
|
|
|
+ } else {
|
|
|
+ var items = source.split(',');
|
|
|
+ if (items.length != 4) {
|
|
|
+ throw ArgumentError("$source can not be parsed to DRect");
|
|
|
+ }
|
|
|
+ rect = DRect(
|
|
|
+ double.parse(items[0]),
|
|
|
+ double.parse(items[1]),
|
|
|
+ double.parse(items[2]),
|
|
|
+ double.parse(items[3]),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return rect;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ String toString() => '$x,$y,$width,$height';
|
|
|
+
|
|
|
+ @override
|
|
|
+ int get hashCode {
|
|
|
+ if (isEmpty) return 0;
|
|
|
+ return x.hashCode ^ y.hashCode ^ width.hashCode ^ height.hashCode;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ bool operator ==(Object other) {
|
|
|
+ if (other is DRect) {
|
|
|
+ if (isEmpty) return other.isEmpty;
|
|
|
+
|
|
|
+ return x == other.x &&
|
|
|
+ y == other.y &&
|
|
|
+ width == other.width &&
|
|
|
+ height == other.height;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool _containsOffsetInner(double x, double y) {
|
|
|
+ return (x >= this.x && x - width <= this.x) &&
|
|
|
+ (y >= this.y && y - height <= this.y);
|
|
|
+ }
|
|
|
+
|
|
|
+ void copyFrom(DRect other) {
|
|
|
+ _x = other.x;
|
|
|
+ _y = other.y;
|
|
|
+ _width = other.width;
|
|
|
+ _height = other.height;
|
|
|
+ }
|
|
|
+}
|