|
@@ -1,727 +1,683 @@
|
|
|
-import 'dart:math';
|
|
|
-import 'dart:ui';
|
|
|
-
|
|
|
-import 'package:fis_common/logger/logger.dart';
|
|
|
-import 'package:fis_jsonrpc/rpc.dart';
|
|
|
-import 'package:fis_measure/interfaces/date_types/point.dart';
|
|
|
-import 'package:fis_measure/interfaces/process/calculators/values.dart';
|
|
|
-import 'package:fis_measure/interfaces/process/items/terms.dart';
|
|
|
-import 'package:fis_measure/interfaces/process/items/types.dart';
|
|
|
-import 'package:fis_measure/process/items/item.dart';
|
|
|
-import 'package:fis_measure/process/primitives/area_abstract.dart';
|
|
|
-import 'package:fis_measure/process/primitives/combos/urm_den_combo.dart';
|
|
|
-import 'package:fis_measure/process/primitives/combos/urm_sr_roi_rect_combo.dart';
|
|
|
-import 'package:fis_measure/process/primitives/combos/urm_vel_combo.dart';
|
|
|
-import 'package:fis_measure/process/primitives/location.dart';
|
|
|
-import 'package:fis_measure/process/primitives/straightline.dart';
|
|
|
-import 'package:fis_measure/process/primitives/urm_rect.dart';
|
|
|
-import 'package:fis_measure/process/primitives/urm_straightline.dart';
|
|
|
-import 'package:fis_measure/process/workspace/urm/application.dart';
|
|
|
-import 'package:vid/us/vid_us_unit.dart';
|
|
|
-
|
|
|
-import 'calculator.dart';
|
|
|
-
|
|
|
-class URMRectCal extends Calculator<URMRect, double> {
|
|
|
- URMRectCal(
|
|
|
- URMRect ref, {
|
|
|
- required this.type,
|
|
|
- }) : super(ref);
|
|
|
- final String type;
|
|
|
- @override
|
|
|
- void calculate() {}
|
|
|
-
|
|
|
- @override
|
|
|
- Future<void> calculateAsync() async {
|
|
|
- if (ref.feature == null) return;
|
|
|
- Size urmResultSize = const Size(0, 0);
|
|
|
- try {
|
|
|
- if (ref.application is! URMApplication) {
|
|
|
- return;
|
|
|
- }
|
|
|
- final URMApplication urmApplication = ref.application as URMApplication;
|
|
|
- urmResultSize = Size(urmApplication.resultWidth.toDouble(),
|
|
|
- urmApplication.resultHeight.toDouble());
|
|
|
- final p1 = ref.feature!.startPoint;
|
|
|
- final p2 = ref.feature!.endPoint;
|
|
|
-
|
|
|
- final leftTopPercent =
|
|
|
- DPoint(p1.x < p2.x ? p1.x : p2.x, p1.y < p2.y ? p1.y : p2.y);
|
|
|
-
|
|
|
- final rightBottomPercent =
|
|
|
- DPoint(p1.x > p2.x ? p1.x : p2.x, p1.y > p2.y ? p1.y : p2.y);
|
|
|
-
|
|
|
- final startPoint = leftTopPercent.scale2Size(urmResultSize);
|
|
|
- final endPoint = rightBottomPercent.scale2Size(urmResultSize);
|
|
|
-
|
|
|
- String description = "URM\n Calculating...";
|
|
|
- updateStringValue(description);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- } catch (e) {
|
|
|
- logger.e('URM Measure error: $e');
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-class URMLocationCal extends Calculator<Location, double> {
|
|
|
- URMLocationCal(Location ref) : super(ref);
|
|
|
-
|
|
|
- @override
|
|
|
- void calculate() {}
|
|
|
-
|
|
|
- @override
|
|
|
- Future<void> calculateAsync() async {
|
|
|
- if (ref.feature == null) return;
|
|
|
- Size urmResultSize = const Size(0, 0);
|
|
|
- try {
|
|
|
- if (ref.application is! URMApplication) {
|
|
|
- return;
|
|
|
- }
|
|
|
- final URMApplication urmApplication = ref.application as URMApplication;
|
|
|
- urmResultSize = Size(urmApplication.resultWidth.toDouble(),
|
|
|
- urmApplication.resultHeight.toDouble());
|
|
|
-
|
|
|
-
|
|
|
- final point = ref.feature!.point.clone();
|
|
|
- final startPoint = point.scale2Size(urmResultSize);
|
|
|
- print("URM Measure startPoint: $startPoint");
|
|
|
-
|
|
|
- return;
|
|
|
- } catch (e) {
|
|
|
- logger.e('URM Measure error: $e');
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-class URMAutoLineLineCal extends Calculator<StraightLine, double> {
|
|
|
- URMAutoLineLineCal(
|
|
|
- StraightLine ref, {
|
|
|
- required this.type,
|
|
|
- }) : super(ref);
|
|
|
- final String type;
|
|
|
- @override
|
|
|
- void calculate() {}
|
|
|
-
|
|
|
- @override
|
|
|
- Future<void> calculateAsync() async {
|
|
|
- try {
|
|
|
- if (ref.feature == null) return;
|
|
|
- if (ref.application is! URMApplication) return;
|
|
|
-
|
|
|
- Size urmResultSize = const Size(0, 0);
|
|
|
- final URMApplication urmApplication = ref.application as URMApplication;
|
|
|
- urmResultSize = Size(urmApplication.resultWidth.toDouble(),
|
|
|
- urmApplication.resultHeight.toDouble());
|
|
|
- final p1 = ref.feature!.startPoint;
|
|
|
- final p2 = ref.feature!.endPoint;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- switch (type) {
|
|
|
- case MeasureTypes.SRCurvature:
|
|
|
- await getSRCurvatureResult(urmApplication, p1, p2);
|
|
|
- break;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- default:
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- logger.e('URM Measure error: $e');
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- Future<void> getSRCurvatureResult(
|
|
|
- URMApplication app, DPoint startPoint, DPoint endPoint) async {
|
|
|
- String description = "URM\n Measuring";
|
|
|
- try {
|
|
|
- URMMeasureProcessResult? result = await app.getURMMeasureResult(
|
|
|
- urmMeasureType: URMMeasureType.URMCurvature,
|
|
|
- rOIType: URMROIType.placeHolder_0,
|
|
|
- srcDPoints: [
|
|
|
- UrmPoint(x: startPoint.x, y: startPoint.y),
|
|
|
- UrmPoint(x: endPoint.x, y: endPoint.y)
|
|
|
- ],
|
|
|
- );
|
|
|
- if (result != null) {
|
|
|
- print(
|
|
|
- "URM Measure curvature: ${result} nums: ${result.resultDPoints?.length}");
|
|
|
-
|
|
|
- final feature = ref.feature!;
|
|
|
- if (feature is! URMAutoLineFeature) return;
|
|
|
- feature.autoLinePoints = urmPointsToDPoints(result.resultDPoints);
|
|
|
-
|
|
|
-
|
|
|
- for (var output in ref.meta.outputs) {
|
|
|
- if (output.name == MeasureTerms.SRCurvature) {
|
|
|
- output.unit = VidUsUnit.None;
|
|
|
- feature.updateFloatValue(output, result.resultData, output.unit);
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- throw Exception("URM Measure API error");
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- description = " ";
|
|
|
- updateStringValue(description);
|
|
|
- return;
|
|
|
- }
|
|
|
- ref.application.updateRenderReady.emit(this, null);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- List<DPoint> urmPointsToDPoints(List<UrmPoint>? points) {
|
|
|
- if (points == null) return [];
|
|
|
- List<DPoint> urmPoints = [];
|
|
|
- for (var point in points) {
|
|
|
- urmPoints.add(DPoint(point.x, point.y));
|
|
|
- }
|
|
|
- return urmPoints;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-class URMTraceCal extends Calculator<AreaItemAbstract, double> {
|
|
|
- URMTraceCal(
|
|
|
- AreaItemAbstract ref, {
|
|
|
- required this.type,
|
|
|
- }) : super(ref);
|
|
|
- final String type;
|
|
|
-
|
|
|
- @override
|
|
|
- void calculate() {}
|
|
|
-
|
|
|
- @override
|
|
|
- Future<void> calculateAsync() async {
|
|
|
- if (ref.feature == null) return;
|
|
|
- final feature = ref.feature!;
|
|
|
- try {
|
|
|
- if (ref.application is! URMApplication) {
|
|
|
- return;
|
|
|
- }
|
|
|
- Size urmResultSize = const Size(0, 0);
|
|
|
- final URMApplication urmApplication = ref.application as URMApplication;
|
|
|
- urmResultSize = Size(urmApplication.resultWidth.toDouble(),
|
|
|
- urmApplication.resultHeight.toDouble());
|
|
|
- final List<DPoint> points =
|
|
|
- feature.innerPoints.map((e) => e.scale2Size(urmResultSize)).toList();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- } catch (e) {
|
|
|
- logger.e('URM Measure error: $e');
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- List<UrmPoint> convertPoints(List<DPoint> points) {
|
|
|
- List<UrmPoint> urmPoints = [];
|
|
|
- for (var point in points) {
|
|
|
- urmPoints.add(UrmPoint(x: point.x, y: point.y));
|
|
|
- }
|
|
|
- return urmPoints;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class URMVelCal extends Calculator<URMVelAbstract, double> {
|
|
|
- URMVelCal(URMVelAbstract ref) : super(ref);
|
|
|
-
|
|
|
- @override
|
|
|
- void calculate() {
|
|
|
- if (ref.feature == null) return;
|
|
|
-
|
|
|
- final a1 = _pickChildValue(ref.child1);
|
|
|
- final a2 = _pickChildValue(ref.child2);
|
|
|
- final a3 = _pickChildValue(ref.child2);
|
|
|
-
|
|
|
- final feature = ref.feature!;
|
|
|
- final viewport = feature.hostVisualArea!.viewport!;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- double? _pickChildValue(MeasureItem item) {
|
|
|
- if (item.calculator == null) return null;
|
|
|
- ValueBase? value;
|
|
|
- if (item.measuredFeatures.isNotEmpty) {
|
|
|
- value = item.measuredFeatures.first.value;
|
|
|
- } else if (item.feature != null) {
|
|
|
- value = item.feature!.value;
|
|
|
- }
|
|
|
- if (value != null && value is FloatValue) {
|
|
|
- return (value).value ?? 0;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class URMDenCal extends Calculator<URMDenAbstract, double> {
|
|
|
- URMDenCal(URMDenAbstract ref) : super(ref);
|
|
|
-
|
|
|
- @override
|
|
|
- void calculate() {
|
|
|
- if (ref.feature == null) return;
|
|
|
-
|
|
|
- final a1 = _pickChildValue(ref.child1);
|
|
|
- final a2 = _pickChildValue(ref.child2);
|
|
|
- final a3 = _pickChildValue(ref.child2);
|
|
|
-
|
|
|
- final feature = ref.feature!;
|
|
|
- final viewport = feature.hostVisualArea!.viewport!;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- double? _pickChildValue(MeasureItem item) {
|
|
|
- if (item.calculator == null) return null;
|
|
|
- ValueBase? value;
|
|
|
- if (item.measuredFeatures.isNotEmpty) {
|
|
|
- value = item.measuredFeatures.first.value;
|
|
|
- } else if (item.feature != null) {
|
|
|
- value = item.feature!.value;
|
|
|
- }
|
|
|
- if (value != null && value is FloatValue) {
|
|
|
- return (value).value ?? 0;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class URMSrDensityCal extends Calculator<URMTwoSRRoiRectAbstract, double> {
|
|
|
- URMSrDensityCal(URMTwoSRRoiRectAbstract ref) : super(ref);
|
|
|
-
|
|
|
- @override
|
|
|
- void calculate() {
|
|
|
- if (ref.feature == null) return;
|
|
|
-
|
|
|
- final a1 = _pickChildValue(ref.child1);
|
|
|
- final a2 = _pickChildValue(ref.child2);
|
|
|
- final a3 = _pickChildValue(ref.child2);
|
|
|
-
|
|
|
- final feature = ref.feature!;
|
|
|
- final viewport = feature.hostVisualArea!.viewport!;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- double? _pickChildValue(MeasureItem item) {
|
|
|
- if (item.calculator == null) return null;
|
|
|
- ValueBase? value;
|
|
|
- if (item.measuredFeatures.isNotEmpty) {
|
|
|
- value = item.measuredFeatures.first.value;
|
|
|
- } else if (item.feature != null) {
|
|
|
- value = item.feature!.value;
|
|
|
- }
|
|
|
- if (value != null && value is FloatValue) {
|
|
|
- return (value).value ?? 0;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|