application.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. import 'dart:math';
  2. import 'package:fis_jsonrpc/services/aIDiagnosis.m.dart';
  3. import 'package:fis_measure/interfaces/date_types/point.dart';
  4. import 'package:fis_measure/interfaces/process/visuals/visual.dart';
  5. import 'package:fis_measure/process/visual/v2d_visual.dart';
  6. import 'package:fis_measure/process/workspace/rpc_bridge.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:vid/us/vid_us_probe.dart';
  9. import '../application.dart';
  10. import 'package:fis_measure/interfaces/date_types/rect_region.dart';
  11. import 'package:vid/us/vid_us_2d_visual.dart';
  12. import 'package:vid/us/vid_us_logical_coordinate.dart';
  13. import 'package:vid/us/vid_us_physical_coordinate.dart';
  14. import 'package:vid/us/vid_us_visual.dart';
  15. import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
  16. /// URM 专业应用
  17. class URMApplication extends Application {
  18. URMApplication(
  19. VidUsProbe probe, {
  20. required this.beams,
  21. required this.samples,
  22. required this.roiRect,
  23. required this.resultWidth,
  24. required this.resultHeight,
  25. required this.remedicalCode,
  26. required this.originVisuals,
  27. this.onUpdateChart,
  28. }) : super(probe);
  29. @override
  30. bool get isThirdPart => true;
  31. List<IVisual> originVisuals; // 原始的视图坐标系
  32. int beams; // 原图有效的beam数量
  33. int samples; // 原图有效的sample数量
  34. Rect roiRect; // ROI区域
  35. int resultWidth; // 分析结果图像宽度
  36. int resultHeight; // 分析结果图像高度
  37. String remedicalCode; // 图像 Code
  38. bool syncDisplay = false; // 是否开启同步显示
  39. double urmPhysicalwidth = 1.0; // URM 结果物理宽度
  40. double urmPhysicalheight = 1.0; // URM 结果物理高度
  41. double areaScaler =
  42. 1.0; // URM 画幅缩放比例 (UrmPhysicalwidth / resultWidth) * (UrmPhysicalheight / resultHeight);
  43. double pixelscaler = 1.0; // URM 像素缩放比例 UrmPhysicalwidth / resultWidth
  44. double urmMinVel = 1.0; // TODO 从分析结果获取该值
  45. final ValueChanged<URMChartParams>? onUpdateChart;
  46. @override
  47. List<IVisual> convertVisuals() {
  48. var urmVisuals = originVisuals;
  49. double beamsPercent = 1;
  50. Size physicalSize = Size.zero;
  51. if (originVisuals.isNotEmpty) {
  52. IVisual visual = originVisuals[0];
  53. if (visual is V2dVisual) {
  54. VidUsVisual visualData = visual.visualData;
  55. if (visualData is VidUs2DVisual) {
  56. if (visualData.logicalCoordinates.isNotEmpty &&
  57. visualData.physicalCoordinates.isNotEmpty) {
  58. beamsPercent = getBeamsPercent(
  59. visualData.logicalCoordinates.entries.first.value,
  60. visualData.physicalCoordinates.entries.first.value,
  61. );
  62. physicalSize = getPhysicalSize(
  63. visualData.physicalCoordinates.entries.first.value);
  64. }
  65. }
  66. double scaleX = roiRect.width / beams * beamsPercent;
  67. double scaleY = roiRect.height / samples;
  68. urmPhysicalwidth = physicalSize.width * roiRect.width / beams;
  69. urmPhysicalheight = physicalSize.height * scaleY;
  70. areaScaler = (urmPhysicalwidth / resultWidth) *
  71. (urmPhysicalheight / resultHeight);
  72. pixelscaler = urmPhysicalwidth / resultWidth;
  73. RectRegion region =
  74. RectRegion(left: 0, top: 0, right: 1 / scaleX, bottom: 1 / scaleY);
  75. V2dVisual v2dVisual = V2dVisual(visualData, region);
  76. urmVisuals = [v2dVisual];
  77. }
  78. }
  79. return urmVisuals;
  80. }
  81. double getBeamsPercent(VidUsLogicalCoordinate logicalCoordinate,
  82. VidUsPhysicalCoordinate physicalCoordinates) {
  83. if (physicalCoordinates is VidUsTissuePhysicalCoordinate) {
  84. return (physicalCoordinates.width /
  85. (logicalCoordinate.region.right - logicalCoordinate.region.left));
  86. }
  87. return 1;
  88. }
  89. Size getPhysicalSize(VidUsPhysicalCoordinate physicalCoordinates) {
  90. if (physicalCoordinates is VidUsTissuePhysicalCoordinate) {
  91. return Size(physicalCoordinates.width,
  92. physicalCoordinates.depthEnd - physicalCoordinates.depthStart);
  93. }
  94. return Size.zero;
  95. }
  96. @override
  97. PointInfo createPointInfo(Offset offset, PointInfoType type) {
  98. final width = displaySize.width;
  99. final height = displaySize.height;
  100. final x = offset.dx / width;
  101. final y = offset.dy / height;
  102. final percentOffset = Offset(x, y);
  103. final info = PointInfo.fromOffset(percentOffset, type);
  104. info.hostVisualArea = currentVisualArea; // 未切换区域则沿用当前区域
  105. if (isAnnotationWorking) {
  106. activeAnnotationItem?.execute(info);
  107. } else {
  108. activeMeasureItem?.execute(info);
  109. if (type == PointInfoType.touchMove) {
  110. mobileTouchEvent.emit(this, offset); // 传出移动事件
  111. }
  112. if (type == PointInfoType.touchUp) {
  113. mobileTouchEndEvent.emit(this, offset); // 传出触摸结束事件
  114. }
  115. }
  116. return info;
  117. }
  118. @override
  119. double get displayScaleRatio {
  120. return max(
  121. 1,
  122. min(displaySize.width / resultWidth,
  123. displaySize.height / resultHeight));
  124. // return 1.0;
  125. }
  126. void loadURMVisuals() {
  127. loadVisuals();
  128. }
  129. // Future<GetSRCurvatureResult?> getSRCurvatureResult(
  130. // DPoint startPoint, DPoint endPoint) async {
  131. // try {
  132. // print("调接口获取测量值 getSRCurvatureAsync");
  133. // GetSRCurvatureResult result =
  134. // await RPCBridge.ins.rpc.aIDiagnosis.getSRCurvatureAsync(
  135. // GetSRCurvatureRequest(
  136. // remedicalCode: remedicalCode,
  137. // measureMode: 5, // 5-URM测量Den,6-URM测量Vel
  138. // dataWidth: resultWidth,
  139. // dataHeight: resultHeight,
  140. // startPointX: startPoint.x,
  141. // startPointY: startPoint.y,
  142. // endPointX: endPoint.x,
  143. // endPointY: endPoint.y,
  144. // token: RPCBridge.ins.userToken,
  145. // ),
  146. // );
  147. // return result;
  148. // } catch (e) {
  149. // return null;
  150. // }
  151. // }
  152. // Future<GetSRRoiVelResult?> getSRRoiVelResult(
  153. // DPoint startPoint, DPoint endPoint) async {
  154. // try {
  155. // print("调接口获取测量值 getSRRoiVelAsync");
  156. // GetSRRoiVelResult result =
  157. // await RPCBridge.ins.rpc.aIDiagnosis.getSRRoiVelAsync(
  158. // GetSRRoiVelRequest(
  159. // remedicalCode: remedicalCode,
  160. // measureMode: 5,
  161. // dataWidth: resultWidth,
  162. // dataHeight: resultHeight,
  163. // startPointX: startPoint.x,
  164. // startPointY: startPoint.y,
  165. // endPointX: endPoint.x,
  166. // endPointY: endPoint.y,
  167. // token: RPCBridge.ins.userToken,
  168. // ),
  169. // );
  170. // return result;
  171. // } catch (e) {
  172. // return null;
  173. // }
  174. // }
  175. // Future<GetSRRoiFractalDimResult?> getSRRoiFractalDimResult(
  176. // DPoint startPoint, DPoint endPoint) async {
  177. // try {
  178. // print("调接口获取测量值 getSRRoiFractalDimAsync");
  179. // GetSRRoiFractalDimResult result =
  180. // await RPCBridge.ins.rpc.aIDiagnosis.getSRRoiFractalDimAsync(
  181. // GetSRRoiFractalDimRequest(
  182. // remedicalCode: remedicalCode,
  183. // measureMode: 5,
  184. // dataWidth: resultWidth,
  185. // dataHeight: resultHeight,
  186. // startPointX: startPoint.x,
  187. // startPointY: startPoint.y,
  188. // endPointX: endPoint.x,
  189. // endPointY: endPoint.y,
  190. // token: RPCBridge.ins.userToken,
  191. // ),
  192. // );
  193. // return result;
  194. // } catch (e) {
  195. // return null;
  196. // }
  197. // }
  198. // Future<GetSRTraceVelResult?> getSRTraceVelResult(
  199. // List<UrmPoint> points,
  200. // ) async {
  201. // try {
  202. // print("调接口获取测量值 getSRTraceVelResult");
  203. // GetSRTraceVelResult result =
  204. // await RPCBridge.ins.rpc.aIDiagnosis.getSRTraceVelAsync(
  205. // GetSRTraceVelRequest(
  206. // remedicalCode: remedicalCode,
  207. // measureMode: 5,
  208. // dataWidth: resultWidth,
  209. // dataHeight: resultHeight,
  210. // inputPoints: points,
  211. // token: RPCBridge.ins.userToken,
  212. // ),
  213. // );
  214. // return result;
  215. // } catch (e) {
  216. // return null;
  217. // }
  218. // }
  219. // Future<GetSRTraceFractalDimResult?> getSRTraceFractalDimResult(
  220. // List<UrmPoint> points,
  221. // ) async {
  222. // try {
  223. // print("调接口获取测量值 getSRTraceFractalDimAsync");
  224. // GetSRTraceFractalDimResult result =
  225. // await RPCBridge.ins.rpc.aIDiagnosis.getSRTraceFractalDimAsync(
  226. // GetSRTraceFractalDimRequest(
  227. // remedicalCode: remedicalCode,
  228. // measureMode: 5,
  229. // dataWidth: resultWidth,
  230. // dataHeight: resultHeight,
  231. // inputPoints: points,
  232. // token: RPCBridge.ins.userToken,
  233. // ),
  234. // );
  235. // return result;
  236. // } catch (e) {
  237. // return null;
  238. // }
  239. // }
  240. // Future<GetSRLoactionVelResult?> getSRLoactionVelResult(
  241. // DPoint point,
  242. // ) async {
  243. // try {
  244. // print("调接口获取测量值 getSRLoactionVelAsync");
  245. // GetSRLoactionVelResult result =
  246. // await RPCBridge.ins.rpc.aIDiagnosis.getSRLoactionVelAsync(
  247. // GetSRLoactionVelRequest(
  248. // remedicalCode: remedicalCode,
  249. // measureMode: 6,
  250. // dataWidth: resultWidth,
  251. // dataHeight: resultHeight,
  252. // startPointX: point.x,
  253. // startPointY: point.y,
  254. // token: RPCBridge.ins.userToken,
  255. // ),
  256. // );
  257. // return result;
  258. // } catch (e) {
  259. // return null;
  260. // }
  261. // }
  262. // Future<GetSRRoiSpeedResult?> getSRRoiSpeedResult(
  263. // DPoint startPoint,
  264. // DPoint endPoint,
  265. // ) async {
  266. // try {
  267. // print("调接口获取测量值 getSRRoiSpeedAsync");
  268. // GetSRRoiSpeedResult result =
  269. // await RPCBridge.ins.rpc.aIDiagnosis.getSRRoiSpeedAsync(
  270. // GetSRRoiSpeedRequest(
  271. // remedicalCode: remedicalCode,
  272. // measureMode: 6,
  273. // dataWidth: resultWidth,
  274. // dataHeight: resultHeight,
  275. // startPointX: startPoint.x,
  276. // startPointY: startPoint.y,
  277. // endPointX: endPoint.x,
  278. // endPointY: endPoint.y,
  279. // token: RPCBridge.ins.userToken,
  280. // ),
  281. // );
  282. // return result;
  283. // } catch (e) {
  284. // return null;
  285. // }
  286. // }
  287. // Future<GetURMDenMeasureResult?> getURMDenMeasureResult(
  288. // DPoint startPoint, DPoint endPoint) async {
  289. // try {
  290. // print("调接口获取测量值 getURMDenMeasureAsync");
  291. // GetURMDenMeasureResult result =
  292. // await RPCBridge.ins.rpc.aIDiagnosis.getURMDenMeasureAsync(
  293. // GetURMDenMeasureRequest(
  294. // remedicalCode: remedicalCode,
  295. // measureMode: 5,
  296. // dataWidth: resultWidth,
  297. // dataHeight: resultHeight,
  298. // startPointX: startPoint.x,
  299. // startPointY: startPoint.y,
  300. // endPointX: endPoint.x,
  301. // endPointY: endPoint.y,
  302. // areaScaler: areaScaler,
  303. // token: RPCBridge.ins.userToken,
  304. // ),
  305. // );
  306. // return result;
  307. // } catch (e) {
  308. // return null;
  309. // }
  310. // }
  311. // Future<GetURMVelMeasureResult?> getURMVelMeasureResult(
  312. // DPoint startPoint, DPoint endPoint) async {
  313. // try {
  314. // print("调接口获取测量值 getURMVelMeasureAsync");
  315. // GetURMVelMeasureResult result =
  316. // await RPCBridge.ins.rpc.aIDiagnosis.getURMVelMeasureAsync(
  317. // GetURMVelMeasureRequest(
  318. // remedicalCode: remedicalCode,
  319. // measureMode: 6,
  320. // dataWidth: resultWidth,
  321. // dataHeight: resultHeight,
  322. // startPointX: startPoint.x,
  323. // startPointY: startPoint.y,
  324. // endPointX: endPoint.x,
  325. // endPointY: endPoint.y,
  326. // areaScaler: areaScaler,
  327. // token: RPCBridge.ins.userToken,
  328. // ),
  329. // );
  330. // return result;
  331. // } catch (e) {
  332. // return null;
  333. // }
  334. // }
  335. // Future<GetUrmVessMeasureResult?> getURMVessMeasureResult(
  336. // DPoint startPoint, DPoint endPoint, double cmlength) async {
  337. // try {
  338. // print("调接口获取测量值 getURMVelMeasureAsync");
  339. // GetUrmVessMeasureResult result =
  340. // await RPCBridge.ins.rpc.aIDiagnosis.getUrmVessMeasureAsync(
  341. // GetUrmVessMeasureRequest(
  342. // remedicalCode: remedicalCode,
  343. // measureMode: 6,
  344. // dataWidth: resultWidth,
  345. // dataHeight: resultHeight,
  346. // startPointX: startPoint.x,
  347. // startPointY: startPoint.y,
  348. // endPointX: endPoint.x,
  349. // endPointY: endPoint.y,
  350. // areaScaler: pixelscaler,
  351. // cmLength: cmlength,
  352. // token: RPCBridge.ins.userToken,
  353. // ),
  354. // );
  355. // return result;
  356. // } catch (e) {
  357. // return null;
  358. // }
  359. // }
  360. }
  361. class URMChartParams {
  362. final List<Point> points;
  363. final double cmlength;
  364. final int maxPointIndex;
  365. final int minPointIndex;
  366. URMChartParams({
  367. required this.points,
  368. required this.cmlength,
  369. required this.maxPointIndex,
  370. required this.minPointIndex,
  371. });
  372. }