123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823 |
- import 'dart:ui';
- import 'dart:math' as math;
- import 'package:fis_measure/interfaces/date_types/point.dart';
- import 'package:fis_measure/interfaces/date_types/vector.dart';
- import 'package:fis_measure/interfaces/enums/items.dart';
- import 'package:fis_measure/interfaces/process/calculators/values.dart';
- import 'package:fis_measure/interfaces/process/items/item.dart';
- import 'package:fis_measure/interfaces/process/items/item_metas.dart';
- import 'package:fis_measure/interfaces/process/items/types.dart';
- import 'package:fis_measure/interfaces/process/workspace/application.dart';
- import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
- import 'package:fis_measure/process/calcuators/curve.dart';
- import 'package:fis_measure/process/calcuators/formulas/general.dart';
- import 'package:fis_measure/process/items/item.dart';
- import 'package:fis_measure/process/items/item_feature.dart';
- import 'package:fis_measure/process/primitives/polyline.dart';
- import 'package:fis_measure/process/primitives/area_abstract.dart';
- import 'package:fis_measure/process/primitives/utils/auto_snap.dart';
- import 'package:fis_measure/process/unit/convert/convert.dart';
- import 'package:fis_measure/utils/canvas.dart';
- import 'package:flutter/foundation.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/rendering.dart';
- import 'package:get/get.dart';
- import 'package:path_drawing/path_drawing.dart';
- import 'package:vid/us/vid_us_unit.dart';
- import 'spline.dart';
- import 'utils/line.dart';
- import 'utils/spline.dart';
- enum LvSimpsonStep {
- none,
- splineBeginEdit,
- splineEditing,
- splineEndEdit,
- splineCompleted,
- done,
- }
- class SimpsonPath extends AreaItemAbstract with AutoSnapMixin {
- static const int splitterCount = 20;
- static const double maxPointsCount = 10000;
- SimpsonPath(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
- PointInfo? firstPoint;
- @protected
- LvSimpsonStep lvSimpsonStep = LvSimpsonStep.none;
- @override
- // SimpsonPathFeature? get feature => super.feature as SimpsonPathFeature;
- SimpsonPathFeature? get feature {
- if (super.feature == null) {
- return null;
- }
- return super.feature as SimpsonPathFeature;
- }
- @override
- bool onExecuteMouse(PointInfo args) {
- if (state == ItemStates.finished) {
- if (args.pointType == PointInfoType.mouseDown) {
- state = ItemStates.waiting;
- lvSimpsonStep = LvSimpsonStep.none;
- snapState = false;
- }
- }
- if (state == ItemStates.waiting) {
- if (args.pointType == PointInfoType.mouseDown) {
- handleMouseDownWhileWaiting(args);
- }
- } else if (state == ItemStates.running) {
- switch (args.pointType) {
- case PointInfoType.mouseUp:
- return false;
- case PointInfoType.mouseDown:
- if (lvSimpsonStep == LvSimpsonStep.splineCompleted) {
- feature!.adjustEndPoint(args.toAreaLogicPoint());
- lvSimpsonStep = LvSimpsonStep.done;
- state = ItemStates.finished;
- // CaliperExtension.ShowCaliper();
- doFeatureFinish();
- } else {
- final lineLen = (args - firstPoint!).length;
- if ((feature!.innerPoints.length > 3 &&
- GeneralFormulas.doubleAlmostEquals(lineLen, 0)) ||
- feature!.innerPoints.length >= maxPointsCount) {
- lvSimpsonStep = LvSimpsonStep.splineCompleted;
- feature!.fixedSpline();
- } else {
- feature!.adopt(args.toAreaLogicPoint());
- }
- }
- break;
- case PointInfoType.mouseMove:
- if (lvSimpsonStep == LvSimpsonStep.splineCompleted) {
- feature!.adjustEndPoint(args.toAreaLogicPoint());
- } else {
- if (!snapState) {
- // checkAutoSnap(args, false);
- if (checkAutoSnap(args, false)) {
- lvSimpsonStep = LvSimpsonStep.splineCompleted;
- feature!.fixedSpline();
- } else {
- feature!.adopt(args.toAreaLogicPoint());
- }
- }
- if (snapState) {
- feature!.updateActivePoint(args.toAreaLogicPoint());
- }
- }
- break;
- default:
- break;
- }
- }
- doCalculate();
- if (args.pointType == PointInfoType.mouseDown) {
- // doFeatureFinish();
- // if (state == ItemStates.waiting || state == ItemStates.finished) {
- if (state == ItemStates.waiting) {
- state = ItemStates.running;
- }
- if (state == ItemStates.running) {
- updateStatus();
- }
- }
- if (args.pointType == PointInfoType.mouseMove) {
- updateStatus();
- }
- return true;
- }
- @override
- bool onExecuteTouch(PointInfo args) {
- // TODO: implement onExecuteTouch
- throw UnimplementedError();
- }
- void handleMouseDownWhileWaiting(PointInfo args) {
- // TODO: 判断是否当前area
- // 转换为Area逻辑位置
- feature = SimpsonPathFeature(this);
- if (args.hostVisualArea != null) {
- feature!.hostVisualArea = args.hostVisualArea;
- }
- final point = args.toAreaLogicPoint();
- feature!.adopt(point);
- feature!.adopt(point);
- state = ItemStates.running;
- firstPoint = args;
- }
- void updateStatus() {
- switch (lvSimpsonStep) {
- case LvSimpsonStep.splineCompleted:
- firstPoint = null;
- if (feature != null) {
- feature!.activeIndex = feature!.innerPoints.length;
- }
- break;
- case LvSimpsonStep.done:
- state = ItemStates.finished;
- if (feature != null) {
- feature!.activeIndex = -1;
- }
- break;
- default:
- break;
- }
- }
- static SimpsonPath create(ItemMeta meta, [IMeasureItem? parent]) {
- final path = SimpsonPath(meta, parent);
- return path;
- }
- }
- class SimpsonPathFeature extends AreaItemFeatureAbstract {
- static const autoGetApexPoint = false; // TODO
- late Map<int, double> horizontalSplitterLegths;
- late DPoint moveBasedPoint;
- IPathGeometry? _pathGeometry;
- List<DPoint>? _splinePoints;
- IPathGeometry? _spline;
- late DPoint _centerLineFixedPoint;
- late DPoint _centerLineMovablePoint;
- late MovablePointsInfo _movablePtsInfo;
- late DPoint _leftPoint;
- late DPoint _rightPoint;
- late DPoint _apexPoint;
- SimpsonPathFeature(AreaItemAbstract refItem) : super(refItem) {
- _splinePoints = [];
- _centerLineFixedPoint = DPointExt.empty;
- _centerLineMovablePoint = DPointExt.empty;
- _movablePtsInfo = MovablePointsInfo.empty();
- _leftPoint = DPointExt.empty;
- _rightPoint = DPointExt.empty;
- _apexPoint = DPointExt.empty;
- moveBasedPoint = DPointExt.empty;
- horizontalSplitterLegths = {};
- }
- @override
- SimpsonPath get refItem => super.refItem as SimpsonPath;
- DPoint get centerLineMovablePoint => _centerLineMovablePoint;
- set centerLineMovablePoint(DPoint val) {
- if (val != _centerLineMovablePoint) {
- _centerLineMovablePoint = val;
- updateSplitters();
- _onVertexPointChanged();
- }
- }
- DPoint get centerLineFixedPoint => _centerLineFixedPoint;
- MovablePointsInfo get movablePtsInfo => _movablePtsInfo;
- set movablePtsInfo(MovablePointsInfo val) {
- if (val != _movablePtsInfo) {
- _movablePtsInfo = val;
- _onSplineMovablePointsInfoChanged();
- }
- }
- DPoint get leftPoint => _leftPoint;
- set leftPoint(DPoint val) {
- if (val != _leftPoint) {
- _leftPoint = val;
- _onVertexPointChanged();
- }
- }
- DPoint get rightPoint => _rightPoint;
- set rightPoint(DPoint val) {
- if (val != _rightPoint) {
- _rightPoint = val;
- _onVertexPointChanged();
- }
- }
- DPoint get apexPoint => _apexPoint;
- set apexPoint(DPoint val) {
- if (val != _apexPoint) {
- _apexPoint = val;
- _onVertexPointChanged();
- }
- }
- double get centerLineLength {
- final p1 = convert2CmPoint(_centerLineFixedPoint);
- final p2 = convert2CmPoint(_centerLineMovablePoint);
- double value = (p2 - p1).length.abs();
- return value;
- }
- double get area {
- final points = innerPoints.map((e) => convert2CmPoint(e)).toList();
- double value = AreaPerimeterCal.calcArea(points);
- return value;
- }
- DPoint convert2CmPoint(DPoint logicPoint) {
- final viewport = hostVisualArea!.viewport!;
- final p = viewport.convert(logicPoint);
- p.x = UnitValueConverter.convert(viewport.xUnit, VidUsUnit.cm, p.x);
- p.y = UnitValueConverter.convert(viewport.yUnit, VidUsUnit.cm, p.y);
- return p;
- }
- bool isClosed = false; // TODO
- @override
- void paint(Canvas canvas, Size size) {
- if (innerPoints.isEmpty) return;
- drawId(canvas, size);
- final points = innerPoints.map((e) => convert2ViewPoint(size, e)).toList();
- final startPoint = points.first;
- drawVertex(canvas, startPoint.toOffset(), points.length == 1);
- if (points.length > 1) {
- final Path path = Path();
- path.moveTo(startPoint.x, startPoint.y);
- for (var i = 1; i < points.length; i++) {
- final point = points[i];
- path.lineTo(point.x, point.y);
- }
- if (isClosed) {
- path.lineTo(startPoint.x, startPoint.y);
- }
- canvas.drawPath(
- path,
- paintLinePan,
- );
- }
- if (_pathGeometry != null) {
- _drawGeometry(canvas, size, _pathGeometry!);
- }
- // 此处仅供调试绘制参考点
- // canvas.drawCircle(
- // convert2ViewPoint(size, centerLineFixedPoint).toOffset(),
- // 10,
- // Paint()
- // ..color = Colors.blue
- // ..style = PaintingStyle.fill,
- // );
- // canvas.drawCircle(
- // convert2ViewPoint(size, centerLineMovablePoint).toOffset(),
- // 10,
- // Paint()
- // ..color = Colors.red
- // ..style = PaintingStyle.fill,
- // );
- drawVertex(canvas, centerLineMovablePoint.toOffset(), isActive);
- }
- void _drawGeometry(Canvas canvas, Size size, IPathGeometry geometry) {
- Path? path;
- if (geometry is PathGeometryContainer) {
- for (var childGeometry in geometry.geometries) {
- _drawGeometry(canvas, size, childGeometry);
- }
- } else if (geometry is PathGeometry) {
- path = Path();
- for (var i = 0; i < geometry.points.length; i++) {
- final point = convert2ViewPoint(size, geometry.points[i]);
- if (i == 0) {
- path.moveTo(point.x, point.y);
- } else {
- path.lineTo(point.x, point.y);
- }
- }
- } else if (geometry is LineGeometry) {
- path = Path();
- DPoint point;
- point = convert2ViewPoint(size, geometry.start);
- path.moveTo(point.x, point.y);
- point = convert2ViewPoint(size, geometry.end);
- path.lineTo(point.x, point.y);
- }
- if (path != null) {
- canvas.drawPath(path, paintLinePan);
- }
- }
- @override
- void adopt(DPoint point) {
- super.adopt(point);
- recreateSpline(false);
- }
- void updateActivePoint(DPoint point) {
- if (activeIndex > 0 && activeIndex <= innerPoints.length) {
- activePoint = point;
- recreateSpline(false);
- }
- }
- DPoint get activePoint {
- if (activeIndex < 0 || activeIndex >= innerPoints.length) {
- throw IndexError.withLength(activeIndex, innerPoints.length);
- }
- return innerPoints[activeIndex];
- }
- set activePoint(DPoint val) {
- if (activeIndex < 0 || activeIndex >= innerPoints.length) {
- throw IndexError.withLength(activeIndex, innerPoints.length);
- }
- innerPoints[activeIndex] = val;
- }
- void fixedSpline() {
- if (innerPoints.isEmpty) {
- return;
- }
- _centerLineFixedPoint = DPoint(
- (innerPoints.last.x + innerPoints.first.x) * 0.5,
- (innerPoints.last.y + innerPoints.first.y) * 0.5,
- );
- var movablePoint = DPoint(0, double.infinity);
- var isFindMin =
- innerPoints[innerPoints.length >> 1].y - innerPoints[0].y < 0;
- if (autoGetApexPoint) {
- movablePoint =
- isFindMin ? movablePoint : DPoint(0, double.negativeInfinity);
- }
- for (DPoint point in innerPoints) {
- if (autoGetApexPoint && innerPoints.isNotEmpty) {
- if (isFindMin) {
- if (point.y < movablePoint.y) {
- movablePoint = point;
- }
- } else {
- if (point.y > movablePoint.y) {
- movablePoint = point;
- }
- }
- } else {
- if (point.y < movablePoint.y) {
- movablePoint = point;
- }
- }
- }
- if (_centerLineMovablePoint != movablePoint) {
- _centerLineMovablePoint = movablePoint;
- if (!_centerLineMovablePoint.isEmpty) {
- // TODO 重设光标位置,暂不支持
- // _centerLineMovablePoint.SynchToMainMonitorScreen(HostArea);
- }
- }
- updateSplitters();
- _onVertexPointChanged();
- }
- void adjustEndPoint(DPoint point) {
- if (innerPoints.isEmpty) {
- return;
- }
- var endPoint = point;
- double minDistance = double.infinity;
- // if (_splinePoints != null && _splinePoints!.isNotEmpty) {
- // for (DPoint splinePoint in _splinePoints!) {
- // double distance = (point - splinePoint).length;
- // if (distance < minDistance) {
- // minDistance = distance;
- // endPoint = splinePoint;
- // }
- // }
- // }
- // TODO: _splinePoints填充和此处时序有问题,先用innerPoints代替,有性能问题,后续解决
- if (innerPoints.isNotEmpty) {
- final splinePoints = innerPoints.take(innerPoints.length - 1);
- for (DPoint splinePoint in splinePoints) {
- double distance = (point - splinePoint).length;
- if (distance < minDistance) {
- minDistance = distance;
- endPoint = splinePoint;
- }
- }
- }
- centerLineMovablePoint = endPoint;
- }
- void recreateSpline(bool isClosed) {
- // if (_breaker.Paused) {
- // return;
- // }
- final generator = SimpsonGeometryGenerator();
- _pathGeometry ??= generator.createPathGeometry();
- double tempCircumference = 0;
- _spline = generator.createSpline(
- innerPoints,
- 0.5,
- null,
- isClosed,
- false,
- 0.005,
- tempCircumference,
- _splinePoints,
- );
- if (_spline != null && _splinePoints != null) {
- // _pathGeometry!.addGeometry(_spline!);
- }
- }
- void updateSplitters() {
- recreateSpline(true);
- if (_spline != null && !_centerLineMovablePoint.isEmpty) {
- var generator = SimpsonGeometryGenerator();
- _pathGeometry!.clear();
- if (innerPoints.isNotEmpty) {
- // _pathGeometry!.addGeometry(_spline!);
- horizontalSplitterLegths = {};
- generator.createSplitters(
- _pathGeometry!,
- _spline!,
- _centerLineFixedPoint,
- _centerLineMovablePoint,
- horizontalSplitterLegths,
- );
- _pathGeometry!.addLineGeometry(
- _centerLineFixedPoint,
- _centerLineMovablePoint,
- );
- }
- }
- }
- void _onVertexPointChanged() {}
- void _onSplineMovablePointsInfoChanged() {}
- }
- class SimpsonGeometryGenerator {
- static const int splitterCount = 20;
- void createSplitters(
- IPathGeometry pathGeometry,
- IPathGeometry spline,
- DPoint centerLineFixedPoint,
- DPoint centerLineMovablePoint,
- Map<int, double> horizontalSplitterLegths,
- ) {
- if (centerLineFixedPoint.isEmpty || centerLineMovablePoint.isEmpty) {
- return;
- }
- // 先放大点,防止计算过程中丢失过多精度,导致角度错误
- final size = Get.find<IApplication>().displaySize;
- DPoint pointA = centerLineFixedPoint.clone().scale2Size(size);
- DPoint pointB = centerLineMovablePoint.clone().scale2Size(size);
- // 用于恢复百分比点
- final reversalSize = Size(1 / size.width, 1 / size.height);
- // Center line
- DVector centerLine = pointB - pointA;
- DVector centerPerLine = centerLine / splitterCount.toDouble();
- final verticalVector = DVector(-centerLine.y, centerLine.x) * 50;
- //Create a 20 splitters path geometry
- PathGeometryContainer temSplittersGeometry = PathGeometryContainer(Path());
- for (var i = 0; i < splitterCount; i++) {
- final center = pointA
- .clone()
- .addVector(centerPerLine * i.toDouble())
- .addVector(centerPerLine / 2);
- DPoint p1 = center.clone().addVector(verticalVector);
- DPoint p2 = center.clone().subtractVector(verticalVector);
- final lineGeometry = LineGeometry(p1, p2);
- temSplittersGeometry.addGeometry(lineGeometry);
- }
- final spline2 = PathGeometryContainer(Path());
- final sss =
- (spline as PathGeometryContainer).geometries.first as PathGeometry;
- spline2.addGeometry(
- PathGeometry(sss.points.map((e) => e.scale2Size(size)).toList()));
- //Get intersection points
- List<DPoint> points = getIntersectionPoints(temSplittersGeometry, spline2);
- List<DPoint> leftPoints = [];
- List<DPoint> rightPoints = [];
- //Split point by center line
- const double constMagnify = 1.0;
- for (DPoint point in points) {
- var magnifyPoint = point.clone();
- magnifyPoint.x *= constMagnify;
- magnifyPoint.y *= constMagnify;
- DVector line = magnifyPoint -
- DPoint(
- (pointA.x + pointB.x) / 2.0 * constMagnify,
- (pointA.y + pointB.y) / 2.0 * constMagnify,
- );
- double angleToCenter = DVector.angleBetween(line, centerLine);
- if (angleToCenter >= 0.0) {
- leftPoints.add(point);
- } else {
- rightPoints.add(point);
- }
- }
- double angleToVertical =
- DVector.angleBetween(verticalVector, DVector(1, 0));
- //order point by vertical axis value
- orderByCalc(DPoint point) => rotaeY(
- point,
- pointA,
- angleToVertical * math.pi / 180.0,
- );
- leftPoints.sort((a, b) {
- final vA = orderByCalc(a);
- final vB = orderByCalc(b);
- return vA.compareTo(vB);
- });
- rightPoints.sort((a, b) {
- final vA = orderByCalc(a);
- final vB = orderByCalc(b);
- return vA.compareTo(vB);
- });
- var finalLeftPoint = leftPoints;
- var finalRightPoint = rightPoints;
- if (finalLeftPoint.length == finalRightPoint.length &&
- finalLeftPoint.length == splitterCount) {
- for (int i = 0; i < splitterCount; i++) {
- // 恢复百分比点
- final pL = finalLeftPoint[i].scale2Size(reversalSize);
- final pR = finalRightPoint[i].scale2Size(reversalSize);
- horizontalSplitterLegths[i + 1] = (pL - pR).length;
- // pathGeometry.addLineGeometry(finalLeftPoint[i], finalRightPoint[i]);
- pathGeometry.addLineGeometry(pL, pR);
- }
- // print("Output!!!!");
- // print(((spline as PathGeometryContainer).geometries.first as PathGeometry)
- // .points);
- // print([centerLineFixedPoint, centerLineMovablePoint]);
- // print(leftPoints);
- // print(rightPoints);
- } else {}
- }
- IPathGeometry? createSpline(
- List<DPoint> sourcePoints,
- double tension,
- List<double>? tensions,
- bool isClosed,
- bool isFilled,
- double tolerance,
- double length,
- List<DPoint>? splinePoints,
- ) {
- length = 0;
- if (sourcePoints.isEmpty) {
- return null;
- }
- // List<DPoint> samplePoints = [];
- // var points = SplineUtils.create(
- // sourcePoints,
- // tension: tension,
- // tensions: tensions,
- // isClosed: isClosed,
- // tolerance: tolerance,
- // closeByStraightLine: true,
- // samplePoints: samplePoints,
- // isSimpsonSpline: true,
- // );
- final points = sourcePoints; // TODO: !!!!!!! 创建收缩Spline有问题,先不计算了,有性能问题再优化
- splinePoints = points;
- final pathGeometry = PathGeometry(points);
- final continer = PathGeometryContainer(Path());
- continer.addGeometry(pathGeometry);
- return continer;
- }
- IPathGeometry createPathGeometry() {
- return PathGeometryContainer(Path());
- }
- static double rotaeY(DPoint point, DPoint cenPoint, double theta) {
- return math.sin(theta) * (point.x - cenPoint.x) +
- math.cos(theta) * (point.y - cenPoint.y) +
- cenPoint.y;
- }
- List<DPoint> getIntersectionPoints(IPathGeometry g1, IPathGeometry g2) {
- final result = <DPoint>[];
- final splittersGeometry = g1 as PathGeometryContainer;
- final splineGeometry =
- (g2 as PathGeometryContainer).geometries.first as PathGeometry;
- for (var splitter in splittersGeometry.geometries) {
- splitter as LineGeometry;
- DPoint lastPoint = splineGeometry.points.first;
- final endLimit = splineGeometry.points.length - 1;
- for (var i = 1; i < splineGeometry.points.length; i++) {
- final currPoint = splineGeometry.points[i];
- final crossPoint = LineUtils.calculateIntersection(
- splitter.start,
- splitter.end,
- lastPoint,
- currPoint,
- );
- if (crossPoint != null) {
- if (LineUtils.isPointOnLine(lastPoint, currPoint, crossPoint)) {
- result.add(crossPoint);
- }
- }
- if (i != endLimit) {
- lastPoint = currPoint;
- }
- }
- }
- return result;
- }
- }
- class PathGeometryContainer implements IPathGeometry {
- final geometries = <IPathGeometry>[];
- late final Path control;
- PathGeometryContainer(Path geometry) {
- control = geometry;
- }
- @override
- void addGeometry(IPathGeometry geometry) {
- geometries.add(geometry);
- }
- @override
- void clear() {
- geometries.clear();
- }
- @override
- void addLineGeometry(
- DPoint centerLineFixedPoint,
- DPoint centerLineMovablePoint,
- ) {
- addGeometry(LineGeometry(centerLineFixedPoint, centerLineMovablePoint));
- }
- }
- class PathGeometry implements IPathGeometry {
- final List<DPoint> points;
- PathGeometry(this.points);
- @override
- void addGeometry(IPathGeometry spline) {}
- @override
- void addLineGeometry(
- DPoint centerLineFixedPoint, DPoint centerLineMovablePoint) {}
- @override
- void clear() {}
- }
- class LineGeometry implements IPathGeometry {
- final DPoint start;
- final DPoint end;
- LineGeometry(this.start, this.end);
- @override
- void addGeometry(IPathGeometry spline) {}
- @override
- void addLineGeometry(
- DPoint centerLineFixedPoint, DPoint centerLineMovablePoint) {}
- @override
- void clear() {}
- void rotateTransform(double angle, double centerX, double centerY) {
- rotatePoint(start, centerX, centerY, angle);
- rotatePoint(end, centerX, centerY, angle);
- }
- static void rotatePoint(
- DPoint point,
- double centerX,
- double centerY,
- double angle,
- ) {
- double radians = angle * math.pi / 180;
- double cosTheta = math.cos(radians);
- double sinTheta = math.sin(radians);
- point.x = centerX +
- (point.x - centerX) * cosTheta -
- (point.y - centerY) * sinTheta;
- point.y = centerY +
- (point.x - centerX) * sinTheta +
- (point.y - centerY) * cosTheta;
- }
- }
- abstract class IPathGeometry {
- void clear();
- void addGeometry(IPathGeometry spline);
- void addLineGeometry(
- DPoint centerLineFixedPoint, DPoint centerLineMovablePoint);
- }
- extension DPointExt on DPoint {
- static final empty = DPoint(double.minPositive, double.minPositive);
- bool get isEmpty {
- return this == empty;
- }
- }
- class MovablePointsInfo {
- int index;
- int start;
- int end;
- MovablePointsInfo(this.index, this.start, this.end);
- factory MovablePointsInfo.empty() {
- return MovablePointsInfo(-1, -1, -1);
- }
- }
|