protected void ReportFeatureSkipped(Feature feature, string reason) { FeaturesSkipped += 1; Feedback.ReportWarning( string.Format("Feature ({0}) skipped: {1}", ProcessingUtils.Format(feature), reason)); Feedback.CurrentFeature = null; ReportFeatureProgress(); }
private static BasicFeatureLayer FindLayer(Map map, FeatureClass featureClass) { if (map == null || featureClass == null) { return(null); } var layers = map.GetLayersAsFlattenedList() .OfType <BasicFeatureLayer>() .Where(lyr => ProcessingUtils.IsSameTable( GetBaseTable(lyr.GetTable()), featureClass)); return(layers.SingleOrDefault()); // bombs if duplicate - ok? }
public CreateAnnoMasksEngine(CreateAnnoMasks config, IProcessingContext context, IProcessingFeedback feedback) : base(config.Name, context, feedback) { _inputDataset = OpenRequiredDataset(config.InputDataset, nameof(config.InputDataset)); _outputMaskDataset = OpenRequiredDataset(config.OutputMaskDataset, nameof(config.OutputMaskDataset)); _relationshipClass = OpenAssociation(config.OutputAssociation); _maskAttributes = ProcessingUtils.CreateFieldSetter( config.MaskAttributes, _outputMaskDataset.FeatureClass, nameof(config.MaskAttributes)); _maskMargin = ImplicitValue.Create(config.MaskMargin, nameof(config.MaskMargin)); _maskMargin.Environment = new StandardEnvironment().RegisterConversionFunctions(); _simplificationToleranceMu = config.SimplificationTolerance; // TODO convert mm to mu _maskOutlineType = config.MaskOutlineType; _fillHoles = config.FillHoles; }
public AlignMarkersEngine(AlignMarkers config, IProcessingContext context, IProcessingFeedback feedback) : base(config.Name, context, feedback) { _inputDataset = OpenRequiredDataset(config.InputDataset, nameof(config.InputDataset)); _referenceDatasets = OpenDatasets(config.ReferenceDatasets); _searchDistance = ProcessingUtils.Clip( config.SearchDistance, 0, double.MaxValue, nameof(config.SearchDistance)); _markerFieldSetter = ProcessingUtils.CreateFieldSetter( config.MarkerAttributes, _inputDataset.FeatureClass, nameof(config.MarkerAttributes)); }
/// <remarks>Caller's duty to dispose features! (See Pro SDK documentation)</remarks> public IEnumerable <Feature> GetOtherFeatures(ProcessingDataset dataset, Geometry extent = null, bool recycling = false) { var filter = ProcessingUtils.CreateFilter(dataset.WhereClause, extent); using (var cursor = dataset.FeatureClass.Search(filter, recycling)) { while (cursor.MoveNext()) { if (cursor.Current is Feature feature) { yield return(feature); } } } }
public async Task Execute(IJobExecutionContext context) { var sw = Stopwatch.StartNew(); var configuration = (ConfigurationItems)context.JobDetail.JobDataMap["configuration"]; var logger = Log.Logger.ForContext <CurrentWeatherSchedulerJob>(); try { await Task.Run(async() => { logger.Information("Use the following parameters for this job:"); logger.Information($"Parallelism: {configuration.Parallelism}"); logger.Information($"Runs every: {configuration.RunsEvery} s"); logger.Information($"Path to Locations file: {configuration.PathToLocationsMap}"); logger.Information($"Write to Elastic index: {configuration.ElasticIndexName}"); logger.Information($"ElasticSearch: {configuration.ElasticHostsAndPorts}"); IFileStorage storage = new FileStorageImpl(); IProcessingUtils processingUtils = new ProcessingUtils(storage); IElasticConnection elasticConnection = new ElasticConnectionBuilder().Build(configuration); ILocationFileReader locationReader = new LocationFileReaderImpl(); IOwmApiReader owmReader = new OwmApiReader(); IOwmToElasticDocumentConverter <CurrentWeatherBase> owmConverter = new OwmToElasticDocumentConverter(); IProcessingBaseImplementations processingBaseImplementations = new ProcessingBaseImplementations(); var processor = new ProcessingBaseCurrentWeatherImpl(elasticConnection, locationReader, owmReader, processingUtils, owmConverter, processingBaseImplementations); await processor.Process(configuration); }); } finally { sw.Stop(); logger.Information("Processed {MethodName} in {ElapsedMs:000} ms", "CurrentWeatherSchedulerJob.Execute", sw.ElapsedMilliseconds); } }
public int CountInputFeatures(ProcessingDataset dataset, Geometry extent = null) { if (SelectionType.IsWithinEditPerimeter()) { var perimeter = GetProcessingPerimeter(); extent = GeometryUtils.Intersection(extent, perimeter); } if (SelectionType.IsSelectedFeatures()) { if (dataset.Selection.SelectionCount < 1) { return(0); } var filter = ProcessingUtils.CreateFilter(dataset.WhereClause, extent); return(dataset.Selection.CountSelection(filter)); } return(CountOtherFeatures(dataset, extent)); }
protected void ReportFeatureFailed(Feature feature, Exception ex) { FeaturesFailed += 1; if (ex is COMException comEx) { Feedback.ReportError( string.Format("Feature ({0}) failed (COMException: ErrorCode = {1}): {2}", ProcessingUtils.Format(feature), comEx.ErrorCode, comEx.Message), comEx); } else { Feedback.ReportError( string.Format("Feature ({0}) failed: {1}", ProcessingUtils.Format(feature), ex.Message), ex); } Feedback.CurrentFeature = null; ReportFeatureProgress(); }
/// <remarks>Caller's duty to dispose features! (See Pro SDK documentation)</remarks> public IEnumerable <Feature> GetInputFeatures(ProcessingDataset dataset, Geometry extent = null, bool recycling = false) { if (SelectionType.IsWithinEditPerimeter()) { var perimeter = GetProcessingPerimeter(); extent = GeometryUtils.Intersection(extent, perimeter); } if (SelectionType.IsSelectedFeatures()) { if (dataset.Selection.SelectionCount < 1) { return(Enumerable.Empty <Feature>()); } var filter = ProcessingUtils.CreateFilter(dataset.WhereClause, extent); return(dataset.Selection.SearchSelection(filter, recycling)); } return(GetOtherFeatures(dataset, extent, recycling)); }
public CalculateControlPointsEngine(CalculateControlPoints config, IProcessingContext context, IProcessingFeedback feedback) : base(config.Name, context, feedback) { _inputDataset = OpenRequiredDataset(config.InputDataset, nameof(config.InputDataset)); _maximumAngle = config.MaximumAngle; if (!(0 <= _maximumAngle && _maximumAngle <= 180)) { throw ConfigError( $"{nameof(config.MaximumAngle)} is {config.MaximumAngle}, not between 0 and 180"); } _controlPointIdValue = ProcessingUtils.Clip( config.ControlPointIdValue, 1, int.MaxValue, nameof(config.ControlPointIdValue)); _simplificationTolerance = ProcessingUtils.Clip( config.SimplificationTolerance, 0, double.MaxValue, nameof(config.SimplificationTolerance)); // TODO convert Millimeters (Points) to MapUnits -- how? }
public int CountOtherFeatures(ProcessingDataset dataset, Geometry extent = null) { QueryFilter filter = ProcessingUtils.CreateFilter(dataset.WhereClause, extent); return(dataset.FeatureClass.GetCount(filter)); }
private void ProcessFeature(Feature feature, [CanBeNull] Polygon perimeter) { Polyline curve; var shape = feature.GetShape(); if (shape is Polygon polygon) { var before = GetPointIDs(polygon); // TODO DEBUG DROP curve = GeometryUtils.Boundary(polygon); } else if (shape is Polyline polyline) { var before = GetPointIDs(polyline); // TODO DEBUG DROP curve = polyline; } else { curve = null; Assert.Fail("Input shape is neither Polyline nor Polygon"); } if (_simplificationTolerance > 0) { curve = GeometryUtils.Generalize(curve, _simplificationTolerance); curve = GeometryUtils.Simplify(curve); } var builder = new PolylineBuilder(curve) { HasID = true }; builder.SetEmpty(); int controlPointsAdded = 0; int controlPointsRemoved = 0; // Things to watch out: // - preserve non-linear segments // - process each part separately // - remember Start/EndPoint or rings foreach (var part in curve.Parts) { var numSegments = part.Count; if (numSegments < 1) { continue; } bool startNewPart = true; var one = part[0]; for (int i = 1; i < numSegments; i++) { var two = part[i]; var centerPoint = two.StartPoint; if (ProcessingUtils.WithinPerimeter(centerPoint, perimeter)) { DoVertex(ref one, ref two, ref controlPointsAdded, ref controlPointsRemoved); } builder.AddSegment(one, startNewPart); startNewPart = false; one = two; } // For polygons (closed rings), also look at Start/EndPoint if (shape is Polygon) { var two = part[0]; var centerPoint = two.StartPoint; if (ProcessingUtils.WithinPerimeter(centerPoint, perimeter)) { DoVertex(ref one, ref two, ref controlPointsAdded, ref controlPointsRemoved); } } builder.AddSegment(one, startNewPart); } if (controlPointsAdded > 0 || controlPointsRemoved > 0) { bool wantPolygon = shape is Polygon; if (wantPolygon) { var polyline = builder.ToGeometry(); shape = PolygonBuilder.CreatePolygon(polyline); } else { shape = builder.ToGeometry(); } var after = GetPointIDs((Multipart)shape); feature.SetShape(shape); feature.Store(); // TODO requires an edit session _msg.DebugFormat("Feature {0}: {1} control points added", ProcessingUtils.Format(feature), controlPointsAdded); ControlPointsAdded += controlPointsAdded; ControlPointsRemoved += controlPointsRemoved; } }
private void ProcessFeature([NotNull] Feature feature) { var shape = feature.GetShape(); var point = Assert.NotNull(shape as MapPoint, "Input shape is not MapPoint"); IDictionary <Feature, double> distanceByFeature = GetNearFeatures(point, _referenceDatasets, _searchDistance); if (distanceByFeature.Count == 0) { _msg.DebugFormat( "Marker feature {0}: No reference feature found within search distance of {1}", ProcessingUtils.Format(feature), _searchDistance); return; } var nearest = distanceByFeature.OrderBy(f => f.Value).First(); var referenceFeature = Assert.NotNull(nearest.Key, "Oops, bug"); var distance = nearest.Value; // may be zero var referenceShape = referenceFeature.GetShape(); var referenceCurve = Assert.NotNull(referenceShape as Multipart, "Reference shape is not Multipart"); double distanceAlongCurve = GeometryUtils.GetDistanceAlongCurve(referenceCurve, point); double normalLength = Math.Max(_inputDataset.XYTolerance, distance); var normalPoly = GeometryEngine.Instance.QueryNormal( referenceCurve, SegmentExtension.NoExtension, distanceAlongCurve, AsRatioOrLength.AsLength, normalLength); var normal = (LineSegment)normalPoly.Parts[0][0]; // TODO safety guards double tangentLength = Math.Max(_inputDataset.XYTolerance, distance); var tangentPoly = GeometryEngine.Instance.QueryTangent( referenceCurve, SegmentExtension.NoExtension, distanceAlongCurve, AsRatioOrLength.AsLength, tangentLength); var tangent = (LineSegment)tangentPoly.Parts[0][0]; // TODO safety guards // ILine.Angle is the angle between line and positive x axis, // but the Angle property of a representation marker has its // zero point at North: add 90° to ILine.Angle to fix: double normalOffset = MathUtils.ToDegrees(normal.Angle) - 90; double normalAngle = ProcessingUtils.ToPositiveDegrees(normalOffset); double tangentOffset = MathUtils.ToDegrees(tangent.Angle) - 90; double tangentAngle = ProcessingUtils.ToPositiveDegrees(tangentOffset); _markerFieldSetter.ForgetAll() .DefineFields(feature, InputQualifier) .DefineFields(referenceFeature, ReferenceQualifier) .DefineValue("normalAngle", normalAngle) .DefineValue("tangentAngle", tangentAngle) .DefineValue("distance", distance) .Execute(feature); feature.Store(); FeaturesAligned += 1; _msg.DebugFormat( "Marker feature {0}: aligned to {1} (normalAngle: {2}, tangentAngle: {3}, distance: {4})", ProcessingUtils.Format(feature), ProcessingUtils.Format(referenceFeature), normalAngle, tangentAngle, distance); // TODO need some mechanism to ensure disposal (required by Pro SDK documentation); see also OneNote foreach (var pair in distanceByFeature) { pair.Key.Dispose(); } }