Эх сурвалжийг харах

add some date_type classes

melon.yin 2 жил өмнө
parent
commit
7524a05103

+ 57 - 0
lib/interfaces/date_types/int_point.dart

@@ -0,0 +1,57 @@
+// import 'dart:math' as math;
+
+import 'package:fis_measure/interfaces/date_types/int_size.dart';
+
+class IntPoint {
+  static final zero = IntPoint(0, 0);
+
+  int _x = 0;
+  int _y = 0;
+
+  // ignore: unnecessary_getters_setters
+  int get x => _x;
+  set x(int value) => _x = value;
+
+  // ignore: unnecessary_getters_setters
+  int get y => _y;
+  set y(int value) => _y = value;
+
+  IntPoint(num x, num y) {
+    _x = x.round();
+    _y = y.round();
+  }
+
+  factory IntPoint.size(IntSize size) {
+    return IntPoint(size.width, size.height);
+  }
+
+  factory IntPoint.dw(int dw) {
+    return IntPoint(LOWORD(dw), HIWORD(dw));
+  }
+
+  void addOffset(int dx, int dy) {
+    x += dx;
+    y += dy;
+  }
+
+  // ignore: non_constant_identifier_names
+  static int HIWORD(int n) {
+    return ((n >> 0x10) & 0xffff);
+  }
+
+// ignore: non_constant_identifier_names
+  static int LOWORD(int n) {
+    return (n & 0xffff);
+  }
+
+  @override
+  bool operator ==(Object other) {
+    return other is IntPoint && x == other.x && y == other.y;
+  }
+
+  @override
+  int get hashCode => x ^ y;
+
+  @override
+  String toString() => '$x,$y';
+}

+ 116 - 0
lib/interfaces/date_types/int_rect.dart

@@ -0,0 +1,116 @@
+// ignore_for_file: unnecessary_getters_setters
+
+import 'dart:math' as math;
+
+class IntRect {
+  static final IntRect empty = IntRect();
+
+  int _left = 0;
+  int _top = 0;
+  int _right = 0;
+  int _bottom = 0;
+
+  IntRect();
+
+  factory IntRect.fill(int left, int top, int width, int height) {
+    final rect = IntRect()
+      .._left = left
+      .._top = top
+      .._right = left + width
+      .._bottom = top + height;
+    return rect;
+  }
+
+  int get left => _left;
+  set left(int value) => _left = value;
+
+  int get right => _right;
+  set right(int value) => _right = value;
+
+  int get top => _top;
+  set top(int value) => _top = value;
+
+  int get bottom => _bottom;
+  set bottom(int value) => _bottom = value;
+
+  int get x => _left;
+
+  int get y => _top;
+
+  int get width => _right - _left;
+  int get height => _bottom - _top;
+
+  bool get isEmpty {
+    return _left == 0 && _top == 0 && _right == 0 && _bottom == 0;
+  }
+
+  bool isValid() {
+    return _left >= 0 && _top >= 0 && _right > _left && _bottom > _top;
+  }
+
+  void reset() {
+    _left = 0;
+    _top = 0;
+    _right = 0;
+    _bottom = 0;
+  }
+
+  void union(IntRect deltaRect) {
+    _left = math.min(_left, deltaRect._left);
+    _right = math.max(_right, deltaRect._right);
+
+    _top = math.min(_top, deltaRect._top);
+    _bottom = math.max(_bottom, deltaRect._bottom);
+  }
+
+  void addOffset(int x, int y) {
+    _left += x;
+    _right += x;
+    _top += y;
+    _bottom += y;
+  }
+
+  bool intersectsWith(IntRect rect) {
+    return _left < _right &&
+        _top < _bottom &&
+        rect._left < rect._right &&
+        rect._top < rect._bottom &&
+        _right > rect._left &&
+        _left < rect._right &&
+        _bottom > rect._top &&
+        _top < rect._bottom;
+  }
+
+  void intersect(IntRect rect) {
+    if (!intersectsWith(rect)) {
+      reset();
+      return;
+    }
+
+    _left = math.max(_left, rect._left);
+    _top = math.max(_top, rect._top);
+    _right = math.min(_right, rect._right);
+    _bottom = math.min(_bottom, rect._bottom);
+  }
+
+  @override
+  bool operator ==(Object other) {
+    return other is IntRect &&
+        _left == other._left &&
+        _top == other._top &&
+        _right == other._right &&
+        _bottom == other._bottom;
+  }
+
+  @override
+  int get hashCode {
+    int hashCode = _left;
+    hashCode = (hashCode * 397) ^ _top;
+    hashCode = (hashCode * 397) ^ _right;
+    hashCode = (hashCode * 397) ^ _bottom;
+    return hashCode;
+  }
+
+  @override
+  String toString() => '$x,$y,$width,$height';
+}

+ 46 - 0
lib/interfaces/date_types/int_size.dart

@@ -0,0 +1,46 @@
+class IntSize {
+  static final IntSize empty = IntSize();
+
+  int _width = 0;
+  int _height = 0;
+
+  IntSize();
+
+  factory IntSize.fill(int width, int height) {
+    if (width < 0 || height < 0) {
+      throw ArgumentError();
+    }
+    return IntSize()
+      .._width = width
+      .._height = height;
+  }
+
+  int get width => _width;
+  set width(int value) {
+    if (value < 0) {
+      throw ArgumentError("Width");
+    }
+    _width = value;
+  }
+
+  int get height => _height;
+  set height(int value) {
+    if (value < 0) {
+      throw ArgumentError("Height");
+    }
+    _height = value;
+  }
+
+  @override
+  bool operator ==(Object other) {
+    return other is IntSize &&
+        _width == other._width &&
+        _height == other._height;
+  }
+
+  @override
+  int get hashCode => _width.hashCode ^ _height.hashCode;
+
+  @override
+  String toString() => 'w:$_width,h:$_height';
+}

+ 655 - 1
lib/interfaces/date_types/matrix.dart

@@ -1 +1,655 @@
-class DMatrix {}
+import 'dart:math' as math;
+
+import 'point.dart';
+import 'sr_segment_infos.dart';
+import 'vector.dart';
+
+enum MatrixTypes {
+  transformIsIdentity,
+  transformIsTranslation,
+  transformIsScaling,
+  placeholder3,
+  transformIsUnknown,
+}
+
+extension _MatrixTypesExt on MatrixTypes {
+  MatrixTypes operator |(MatrixTypes other) {
+    final idx = index | other.index;
+    return MatrixTypes.values[idx];
+  }
+}
+
+class DMatrix {
+  static DMatrix identity = DMatrix()
+    ..setMatrix(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, MatrixTypes.transformIsIdentity);
+
+  /* Private Fields */
+
+  double _m11 = 0.0;
+  double _m12 = 0.0;
+  double _m21 = 0.0;
+  double _m22 = 0.0;
+  double _offsetX = 0.0;
+  double _offsetY = 0.0;
+  MatrixTypes _type = MatrixTypes.transformIsIdentity;
+  int _padding = 0;
+
+/* Contructions */
+
+  DMatrix();
+
+  factory DMatrix.fill(
+    double m11,
+    double m12,
+    double m21,
+    double m22,
+    double offsetX,
+    double offsetY,
+  ) {
+    final m = DMatrix();
+    m._m11 = m11;
+    m._m12 = m12;
+    m._m21 = m21;
+    m._m22 = m22;
+    m._offsetX = offsetX;
+    m._offsetY = offsetY;
+    m._type = MatrixTypes.transformIsUnknown;
+    m._padding = 0;
+    m._deriveMatrixType();
+    return m;
+  }
+
+/* Properties */
+
+  bool get _isDistinguishedIdentity => _type == MatrixTypes.transformIsIdentity;
+  bool get isIdentity {
+    if ((_type == MatrixTypes.transformIsIdentity)) return true;
+    final idM1 = (_m11 == 1.0) && (_m12 == 0.0);
+    final idM2 = (_m21 == 0.0) && (_m22 == 1.0);
+    return (idM1 && idM2) && (_offsetX == 0.0) && (_offsetY == 0.0);
+  }
+
+  double get m11 {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      return 1.0;
+    }
+    return _m11;
+  }
+
+  set m11(double value) {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      setMatrix(value, 0.0, 0.0, 1.0, 0.0, 0.0, MatrixTypes.transformIsScaling);
+    } else {
+      _m11 = value;
+      if (_type != MatrixTypes.transformIsUnknown) {
+        _type = _type |= MatrixTypes.transformIsScaling;
+      }
+    }
+  }
+
+  double get m12 {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      return 0.0;
+    }
+    return _m12;
+  }
+
+  set m12(double value) {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      setMatrix(1.0, value, 0.0, 1.0, 0.0, 0.0, MatrixTypes.transformIsUnknown);
+    } else {
+      _m12 = value;
+      _type = MatrixTypes.transformIsUnknown;
+    }
+  }
+
+  double get m21 {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      return 0.0;
+    }
+    return _m21;
+  }
+
+  set m21(double value) {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      setMatrix(1.0, 0.0, value, 1.0, 0.0, 0.0, MatrixTypes.transformIsUnknown);
+    } else {
+      _m21 = value;
+      _type = MatrixTypes.transformIsUnknown;
+    }
+  }
+
+  double get m22 {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      return 1.0;
+    }
+    return _m22;
+  }
+
+  set m22(double value) {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      setMatrix(1.0, 0.0, 0.0, value, 0.0, 0.0, MatrixTypes.transformIsScaling);
+    } else {
+      _m22 = value;
+      if (_type != MatrixTypes.transformIsUnknown) {
+        _type |= MatrixTypes.transformIsScaling;
+      }
+    }
+  }
+
+  double get offsetX {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      return 0.0;
+    }
+    return _offsetX;
+  }
+
+  set offsetX(double value) {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      setMatrix(
+          1.0, 0.0, 0.0, 1.0, value, 0.0, MatrixTypes.transformIsTranslation);
+    } else {
+      _offsetX = value;
+      if (_type != MatrixTypes.transformIsUnknown) {
+        _type |= MatrixTypes.transformIsTranslation;
+      }
+    }
+  }
+
+  double get offsetY {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      return 0.0;
+    }
+    return _offsetY;
+  }
+
+  set offsetY(double value) {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      setMatrix(
+          1.0, 0.0, 0.0, 1.0, 0.0, value, MatrixTypes.transformIsTranslation);
+    } else {
+      _offsetY = value;
+      if (_type != MatrixTypes.transformIsUnknown) {
+        _type |= MatrixTypes.transformIsTranslation;
+      }
+    }
+  }
+
+  double get determinant {
+    switch (_type) {
+      case MatrixTypes.transformIsIdentity:
+      case MatrixTypes.transformIsTranslation:
+        return 1.0;
+
+      case MatrixTypes.transformIsScaling:
+      case MatrixTypes.placeholder3:
+        //(MatrixTypes.TRANSFORM_IS_SCALING | MatrixTypes.TRANSFORM_IS_TRANSLATION)
+        return (_m11 * _m22);
+      default:
+        break;
+    }
+    return (_m11 * _m22) - (_m12 * _m21);
+  }
+
+  bool get hasInverse {
+    return !_DoubleUtil.isZero(determinant);
+  }
+
+  /* Public Methods */
+
+  void invert() {
+    if (_DoubleUtil.isZero(determinant)) {
+      throw Exception("Transform_NotInvertible");
+    }
+    switch (_type) {
+      case MatrixTypes.transformIsIdentity:
+        break;
+      case MatrixTypes.transformIsTranslation:
+        _offsetX = -_offsetX;
+        _offsetY = -_offsetY;
+        return;
+      case MatrixTypes.transformIsScaling:
+        _m11 = 1.0 / _m11;
+        _m22 = 1.0 / _m22;
+        return;
+      case MatrixTypes.placeholder3:
+        //(MatrixTypes.TRANSFORM_IS_SCALING | MatrixTypes.TRANSFORM_IS_TRANSLATION)
+        _m11 = 1.0 / _m11;
+        _m22 = 1.0 / _m22;
+        _offsetX = -_offsetX * _m11;
+        _offsetY = -_offsetY * _m22;
+        return;
+      default:
+        {
+          double num2 = 1.0 / determinant;
+          setMatrix(
+            _m22 * num2,
+            -_m12 * num2,
+            -_m21 * num2,
+            _m11 * num2,
+            ((_m21 * _offsetY) - (_offsetX * _m22)) * num2,
+            ((_offsetX * _m12) - (_m11 * _offsetY)) * num2,
+            MatrixTypes.transformIsUnknown,
+          );
+          break;
+        }
+    }
+  }
+
+  void multiplyVector(DVector vector) {
+    double x = vector.x;
+    double y = vector.y;
+    switch (_type) {
+      case MatrixTypes.transformIsIdentity:
+      case MatrixTypes.transformIsTranslation:
+        return;
+
+      case MatrixTypes.transformIsScaling:
+      case MatrixTypes
+          .placeholder3: // MatrixTypes.transformIsScaling | MatrixTypes.transformIsTranslation;
+        x *= _m11;
+        y *= _m22;
+        return;
+      default:
+        break;
+    }
+    double num = y * _m21;
+    double num2 = x * _m12;
+    x *= _m11;
+    x += num;
+    y *= _m22;
+    y += num2;
+    vector.x = x;
+    vector.y = y;
+  }
+
+  void multiplyPoint(DPoint point) {
+    double x = point.x;
+    double y = point.y;
+    switch (_type) {
+      case MatrixTypes.transformIsIdentity:
+        return;
+
+      case MatrixTypes.transformIsTranslation:
+        x += _offsetX;
+        y += _offsetY;
+        return;
+
+      case MatrixTypes.transformIsScaling:
+        x *= _m11;
+        y *= _m22;
+        return;
+
+      case MatrixTypes
+          .placeholder3: // MatrixTypes.transformIsScaling | MatrixTypes.transformIsTranslation;
+        x *= _m11;
+        x += _offsetX;
+        y *= _m22;
+        y += _offsetY;
+        return;
+      default:
+        break;
+    }
+    double num = (y * _m21) + _offsetX;
+    double num2 = (x * _m12) + _offsetY;
+    x *= _m11;
+    x += num;
+    y *= _m22;
+    y += num2;
+    point.x = x;
+    point.y = y;
+  }
+
+  void setMatrix(
+    double m11,
+    double m12,
+    double m21,
+    double m22,
+    double offsetX,
+    double offsetY,
+    MatrixTypes type,
+  ) {
+    _m11 = m11;
+    _m12 = m12;
+    _m21 = m21;
+    _m22 = m22;
+    _offsetX = offsetX;
+    _offsetY = offsetY;
+    _type = type;
+  }
+
+  void copyFrom(DMatrix other) {
+    setMatrix(
+      other.m11,
+      other.m12,
+      other.m21,
+      other.m22,
+      other.offsetX,
+      other.offsetY,
+      other._type,
+    );
+  }
+
+  void skew(double skewX, double skewY) {
+    skewX = skewX % 360.0;
+    skewY = skewY % 360.0;
+    final radians = createSkewRadians(
+      skewX * 0.017453292519943295,
+      skewY * 0.017453292519943295,
+    );
+    final outcome = this * radians;
+    copyFrom(outcome);
+  }
+
+  void apppend(DMatrix matrix) {
+    final outcome = this * matrix;
+    copyFrom(outcome);
+  }
+
+  void rotateAt(double angle, double centerX, double centerY) {
+    angle = angle % 360.0;
+    final outcome = this *
+        createRotationRadiansAt(
+          angle * 0.017453292519943295,
+          centerX,
+          centerY,
+        );
+    copyFrom(outcome);
+  }
+
+  void scale(double scaleX, double scaleY) {
+    final outcome = this * createScaling(scaleX, scaleY);
+    copyFrom(outcome);
+  }
+
+  void scaleAt(
+    double scaleX,
+    double scaleY,
+    double centerX,
+    double centerY,
+  ) {
+    final outcome = this * createScalingAt(scaleX, scaleY, centerX, centerY);
+    copyFrom(outcome);
+  }
+
+  void translate(double offsetX, double offsetY) {
+    if (_type == MatrixTypes.transformIsIdentity) {
+      setMatrix(
+        1.0,
+        0.0,
+        0.0,
+        1.0,
+        offsetX,
+        offsetY,
+        MatrixTypes.transformIsTranslation,
+      );
+    } else if (_type == MatrixTypes.transformIsUnknown) {
+      _offsetX += offsetX;
+      _offsetY += offsetY;
+    } else {
+      _offsetX += offsetX;
+      _offsetY += offsetY;
+      _type |= MatrixTypes.transformIsTranslation;
+    }
+  }
+
+  DPoint transformWidthPoint(DPoint point) {
+    DPoint point2 = point;
+    multiplyPoint(point2);
+    return point2;
+  }
+
+  VecPoint transformWithVecPoint(VecPoint point) {
+    final vPoint = VecPoint();
+    final dPoint = DPoint(point.x, point.y);
+    multiplyPoint(dPoint);
+    final ddPoint = DPoint(point.x + point.dx, point.y + point.dy);
+    multiplyPoint(ddPoint);
+    vPoint.x = dPoint.x;
+    vPoint.y = dPoint.y;
+    vPoint.dx = ddPoint.x - dPoint.x;
+    vPoint.dy = ddPoint.y - dPoint.y;
+    return vPoint;
+  }
+
+  void transformWithPoints(List<DPoint>? points) {
+    if (points != null) {
+      for (int i = 0; i < points.length; i++) {
+        multiplyPoint(points[i]);
+      }
+    }
+  }
+
+  DVector transformWithVector(DVector vector) {
+    DVector vector2 = vector;
+    multiplyVector(vector2);
+    return vector2;
+  }
+
+  void transformWithVectors(List<DVector>? vectors) {
+    if (vectors != null) {
+      for (int i = 0; i < vectors.length; i++) {
+        multiplyVector(vectors[i]);
+      }
+    }
+  }
+
+  /* Public Static Methods */
+
+  static DMatrix createRotationRadians(double angle) {
+    return createRotationRadiansAt(angle, 0.0, 0.0);
+  }
+
+  static DMatrix createRotationRadiansAt(
+    double angle,
+    double centerX,
+    double centerY,
+  ) {
+    DMatrix matrix = DMatrix();
+    double num = math.sin(angle);
+    double num2 = math.cos(angle);
+    double offsetX = (centerX * (1.0 - num2)) + (centerY * num);
+    double offsetY = (centerY * (1.0 - num2)) - (centerX * num);
+    matrix.setMatrix(
+      num2,
+      num,
+      -num,
+      num2,
+      offsetX,
+      offsetY,
+      MatrixTypes.transformIsUnknown,
+    );
+    return matrix;
+  }
+
+  static DMatrix createScalingAt(
+    double scaleX,
+    double scaleY,
+    double centerX,
+    double centerY,
+  ) {
+    DMatrix matrix = DMatrix();
+    matrix.setMatrix(
+      scaleX,
+      0.0,
+      0.0,
+      scaleY,
+      centerX - (scaleX * centerX),
+      centerY - (scaleY * centerY),
+      MatrixTypes.transformIsScaling | MatrixTypes.transformIsTranslation,
+    );
+    return matrix;
+  }
+
+  static DMatrix createScaling(double scaleX, double scaleY) {
+    DMatrix matrix = DMatrix();
+    matrix.setMatrix(
+      scaleX,
+      0.0,
+      0.0,
+      scaleY,
+      0.0,
+      0.0,
+      MatrixTypes.transformIsScaling,
+    );
+    return matrix;
+  }
+
+  static DMatrix createSkewRadians(double skewX, double skewY) {
+    final matrix = DMatrix()
+      ..setMatrix(
+        1.0,
+        math.tan(skewY),
+        math.tan(skewX),
+        1.0,
+        0.0,
+        0.0,
+        MatrixTypes.transformIsUnknown,
+      );
+    return matrix;
+  }
+
+  /* Operators & Override methods */
+
+  DMatrix operator *(DMatrix other) {
+    MatrixUtil.multiplyMatrix(this, other);
+    return this;
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is DMatrix) {
+      if (_isDistinguishedIdentity || other._isDistinguishedIdentity) {
+        return (isIdentity == other.isIdentity);
+      }
+      final m1Equals = (m11 == other.m11) && (m12 == other.m12);
+      final m2Equals = (m21 == other.m21) && (m22 == other.m22);
+      return (m1Equals && m2Equals) &&
+          (offsetX == other.offsetX) &&
+          (offsetY == other.offsetY);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    if (_isDistinguishedIdentity) return 0;
+    return (((((m11.hashCode ^ m12.hashCode) ^ m21.hashCode) ^ m22.hashCode) ^
+            offsetX.hashCode) ^
+        offsetY.hashCode);
+  }
+
+  void _deriveMatrixType() {
+    _type = MatrixTypes.transformIsIdentity;
+    if ((_m21 != 0.0) || (_m12 != 0.0)) {
+      _type = MatrixTypes.transformIsUnknown;
+    } else {
+      if ((_m11 != 1.0) || (_m22 != 1.0)) {
+        _type = MatrixTypes.transformIsScaling;
+      }
+
+      if ((_offsetX != 0.0) || (_offsetY != 0.0)) {
+        var typeIdx = _type.index;
+        typeIdx |= MatrixTypes.transformIsTranslation.index;
+        _type = MatrixTypes.values[typeIdx];
+      }
+      if ((_type.index &
+              (MatrixTypes.transformIsScaling.index |
+                  MatrixTypes.transformIsTranslation.index)) ==
+          MatrixTypes.transformIsIdentity.index) {
+        _type = MatrixTypes.transformIsIdentity;
+      }
+    }
+  }
+}
+
+class MatrixUtil {
+  static void multiplyMatrix(DMatrix matrix1, DMatrix matrix2) {
+    MatrixTypes types = matrix1._type;
+    MatrixTypes types2 = matrix2._type;
+    if (types2 != MatrixTypes.transformIsIdentity) {
+      if (types == MatrixTypes.transformIsIdentity) {
+        matrix1 = matrix2;
+      } else if (types2 == MatrixTypes.transformIsTranslation) {
+        matrix1._offsetX += matrix2._offsetX;
+        matrix1._offsetY += matrix2._offsetY;
+        if (types != MatrixTypes.transformIsUnknown) {
+          matrix1._type |= MatrixTypes.values[1];
+          //*((int*)&matrix1._type) |= 1;
+        }
+      } else if (types == MatrixTypes.transformIsTranslation) {
+        double num2 = matrix1._offsetX;
+        double num3 = matrix1._offsetY;
+        matrix1 = matrix2;
+        matrix1._offsetX =
+            ((num2 * matrix2._m11) + (num3 * matrix2._m21)) + matrix2._offsetX;
+        matrix1._offsetY =
+            ((num2 * matrix2._m12) + (num3 * matrix2._m22)) + matrix2._offsetY;
+        if (types2 == MatrixTypes.transformIsUnknown) {
+          matrix1._type = MatrixTypes.transformIsUnknown;
+        } else {
+          matrix1._type = MatrixTypes.transformIsUnknown |
+              MatrixTypes.transformIsTranslation;
+        }
+      } else {
+        final typeIdx = (types.index << 4) | types2.index;
+        switch (typeIdx) {
+          case 0x22:
+            matrix1._m11 *= matrix2._m11;
+            matrix1._m22 *= matrix2._m22;
+            return;
+
+          case 0x23:
+            matrix1._m11 *= matrix2._m11;
+            matrix1._m22 *= matrix2._m22;
+            matrix1._offsetX = matrix2._offsetX;
+            matrix1._offsetY = matrix2._offsetY;
+            matrix1._type = MatrixTypes.transformIsScaling |
+                MatrixTypes.transformIsTranslation;
+            return;
+
+          case 0x24:
+          case 0x34:
+          case 0x42:
+          case 0x43:
+          case 0x44:
+            matrix1 = DMatrix.fill(
+              (matrix1._m11 * matrix2._m11) + (matrix1._m12 * matrix2._m21),
+              (matrix1._m11 * matrix2._m12) + (matrix1._m12 * matrix2._m22),
+              (matrix1._m21 * matrix2._m11) + (matrix1._m22 * matrix2._m21),
+              (matrix1._m21 * matrix2._m12) + (matrix1._m22 * matrix2._m22),
+              ((matrix1._offsetX * matrix2._m11) +
+                      (matrix1._offsetY * matrix2._m21)) +
+                  matrix2._offsetX,
+              ((matrix1._offsetX * matrix2._m12) +
+                      (matrix1._offsetY * matrix2._m22)) +
+                  matrix2._offsetY,
+            );
+            return;
+
+          case 50:
+            matrix1._m11 *= matrix2._m11;
+            matrix1._m22 *= matrix2._m22;
+            matrix1._offsetX *= matrix2._m11;
+            matrix1._offsetY *= matrix2._m22;
+            return;
+
+          case 0x33:
+            matrix1._m11 *= matrix2._m11;
+            matrix1._m22 *= matrix2._m22;
+            matrix1._offsetX =
+                (matrix2._m11 * matrix1._offsetX) + matrix2._offsetX;
+            matrix1._offsetY =
+                (matrix2._m22 * matrix1._offsetY) + matrix2._offsetY;
+            return;
+        }
+      }
+    }
+  }
+}
+
+class _DoubleUtil {
+  static bool isZero(double value) {
+    return (value.abs() < 2.2204460492503131E-15);
+  }
+}

+ 42 - 1
lib/interfaces/date_types/skew_transform.dart

@@ -1 +1,42 @@
-class DSkewTransform {}
+import 'matrix.dart';
+import 'point.dart';
+
+class DSkewTransform {
+  DMatrix _matrix = DMatrix();
+
+  DSkewTransform._();
+
+  factory DSkewTransform(
+    double angleX,
+    double angleY,
+    double centerX,
+    double centerY,
+  ) {
+    final st = DSkewTransform._();
+    bool flag = (centerX != 0.0) || !(centerY == 0.0);
+    if (flag) {
+      st._matrix.translate(-centerX, -centerY);
+    }
+    st._matrix.skew(angleX, angleY);
+    if (flag) {
+      st._matrix.translate(centerX, centerY);
+    }
+    return st;
+  }
+
+  factory DSkewTransform.withMatrix(DMatrix matrix) {
+    final st = DSkewTransform._();
+    st._matrix = matrix;
+    return st;
+  }
+
+  DSkewTransform get inverse {
+    final inversedMatrix = _matrix..invert();
+    final st = DSkewTransform.withMatrix(inversedMatrix);
+    return st;
+  }
+
+  DPoint transform(DPoint point) {
+    return _matrix.transformWidthPoint(point);
+  }
+}

+ 14 - 0
lib/interfaces/date_types/sr_segment_infos.dart

@@ -0,0 +1,14 @@
+class VecPoint {
+  double x = 0;
+  double y = 0;
+  double dx = 0;
+  double dy = 0;
+
+  static VecPoint average(VecPoint left, VecPoint right) {
+    return VecPoint()
+      ..x = (left.x + right.x) / 2
+      ..y = (left.y + right.y) / 2
+      ..dx = (left.dx + right.dx) / 2
+      ..dy = (left.dy + right.dy) / 2;
+  }
+}

+ 41 - 1
lib/interfaces/date_types/vector.dart

@@ -1,5 +1,45 @@
+import 'dart:math' as math;
+
 class DVector {
   double x = 0;
   double y = 0;
-  DVector(double x, double y);
+
+  DVector(this.x, this.y);
+
+  double get length => math.sqrt(lengthSquared);
+
+  double get lengthSquared => (math.pow(x, 2) + math.pow(y, 2)).toDouble();
+
+  static DVector parse(String source) {
+    var splits = source.split(',');
+    if (splits.length != 2) {
+      throw ArgumentError("Parse $source to DVector failed");
+    }
+    return DVector(double.parse(splits[0]), double.parse(splits[1]));
+  }
+
+  static double angleBetween(DVector vector1, DVector vector2) {
+    double y = (vector1.x * vector2.y) - (vector2.x * vector1.y);
+    double x = (vector1.x * vector2.x) + (vector1.y * vector2.y);
+    return (math.atan2(y, x) * 57.295779513082323);
+  }
+
+  @override
+  bool operator ==(Object other) {
+    return other is DVector && x == other.x && y == other.y;
+  }
+
+  DVector operator *(double scalar) {
+    return DVector(x * scalar, y * scalar);
+  }
+
+  DVector operator /(double scalar) {
+    return this * (1.0 / scalar);
+  }
+
+  @override
+  int get hashCode => x.hashCode ^ y.hashCode;
+
+  @override
+  String toString() => '$x,$y';
 }