private static bool IsLinesIntersected(ProfileSurfacePoint firstStartPoint, ProfileSurfacePoint firstEndPoint, ProfileSurfacePoint secondStartPoint, ProfileSurfacePoint secondEndPoint) { const double epsilon = 1e-10; var firstLineVectorDiff = PointsDiff(firstEndPoint, firstStartPoint); var secondLineVectorDiff = PointsDiff(secondEndPoint, secondStartPoint); var startPointsDiff = PointsDiff(secondStartPoint, firstStartPoint); var diffCross = VectorCross(firstLineVectorDiff, secondLineVectorDiff); var startPointsCrossToFirst = VectorCross(startPointsDiff, firstLineVectorDiff); if (Math.Abs(diffCross) < epsilon && Math.Abs(startPointsCrossToFirst) < epsilon) { var firstLineProduct = PointsProduct(startPointsDiff, firstLineVectorDiff); var secondLineProduct = PointsProduct(PointsDiff(firstStartPoint, secondStartPoint), secondLineVectorDiff); if ((firstLineProduct >= 0 && firstLineProduct <= VectorCross(firstLineVectorDiff, firstLineVectorDiff)) || (secondLineProduct >= 0 && secondLineProduct <= VectorCross(secondLineVectorDiff, secondLineVectorDiff))) { return(true); } return(false); } var t = VectorCross(startPointsDiff, secondLineVectorDiff) / diffCross; var u = startPointsCrossToFirst / diffCross; if (!(Math.Abs(diffCross) < epsilon) && (0 <= t && t <= 1) && (0 <= u && u <= 1)) { return(true); } return(false); }
private static double CalcVectorLength(ProfileSurfacePoint leftPoint, ProfileSurfacePoint rightPoint) { var x = rightPoint.Distance - leftPoint.Distance; var y = rightPoint.Z - leftPoint.Z; return(Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2))); }
private double CalcAngleOfDeviation(ProfileSurfacePoint leftPoint, ProfileSurfacePoint rightPoint) { var angle = Math.Atan(Math.Abs(rightPoint.Z - leftPoint.Z) / (rightPoint.Distance - leftPoint.Distance)) * (180 / Math.PI); return((rightPoint.Z < leftPoint.Z) ? angle * (-1) : angle); }
private static double CalcAngleOfDeviation(ProfileSurfacePoint leftPoint, ProfileSurfacePoint rightPoint) { var angle = Math.Atan(Math.Abs(rightPoint.Z - leftPoint.Z) / (rightPoint.Distance - leftPoint.Distance)); angle = RadiansToDegrees(angle); return((rightPoint.Z < leftPoint.Z) ? angle * (-1) : angle); }
internal static IPoint GetObserverPoint(double observerHeight, ProfileSurfacePoint firstPoint) { IPoint geoPoint = new Point() { X = firstPoint.X, Y = firstPoint.Y, Z = firstPoint.Z, SpatialReference = EsriTools.Wgs84Spatialreference }; return(EsriTools.GetObserverPoint(geoPoint, observerHeight, ArcMap.Document.FocusMap.SpatialReference)); }
private static double CalcAngleOfVisibility(double observerHeight, ProfileSurfacePoint leftPoint, ProfileSurfacePoint rightPoint, double firstPointDistance) { var sightLineKoef = (rightPoint.Z - observerHeight) / (rightPoint.Distance - firstPointDistance); var surfaceLineKoef = (rightPoint.Z - leftPoint.Z) / (rightPoint.Distance - leftPoint.Distance); var result = (surfaceLineKoef - sightLineKoef) / (1 + surfaceLineKoef * sightLineKoef); return(Math.Atan(result)); }
private List <double> FindAngles(ProfileSurfacePoint[] profileSurfacePoints) { var angles = new List <double>(); ProfileSurfacePoint deviationPoint = profileSurfacePoints[0]; for (var i = 0; i < profileSurfacePoints.Length - 2; i++) { if (CalcAngleOfDeviation(profileSurfacePoints[i], profileSurfacePoints[i + 1]) != CalcAngleOfDeviation(profileSurfacePoints[i + 1], profileSurfacePoints[i + 2])) { angles.Add(CalcAngleOfDeviation(deviationPoint, profileSurfacePoints[i + 1])); deviationPoint = profileSurfacePoints[i + 1]; } else { _triangle.Add(profileSurfacePoints[i + 1]); } } return(angles); }
internal void AddVertexPointsToLine(List <ProfileSurface> segments, double observerHeight) { _surfaceProfileChart.AddVertexPoint(segments[0].ProfileSurfacePoints.First(), true, segments[0].LineId, observerHeight); for (int i = 0; i < segments.Count(); i++) { var isVisible = true; var points = segments[i].ProfileSurfacePoints; var minHeightPoint = (points[0].Z > points.Last().Z) ? points.Last().Z : points[0].Z; minHeightPoint += observerHeight; for (int j = 0; j < points.Count() - 1; j++) { if (points[j].Z < minHeightPoint && points[j + 1].Z < minHeightPoint) { continue; } var vertex = new ProfileSurfacePoint { Z = points[0].Z + observerHeight, Distance = points[0].Distance }; var vertexNext = new ProfileSurfacePoint { Z = points.Last().Z + observerHeight, Distance = points.Last().Distance }; if (IsLinesIntersected(vertex, vertexNext, points[j], points[j + 1])) { isVisible = false; break; } } _surfaceProfileChart.AddVertexPoint(points.Last(), isVisible, segments[i].LineId, observerHeight); } }
internal void AddExtremePoint(ProfileSurfacePoint observerPoint, ProfileSurfacePoint observationPoint, int order) { profileChart.Series.Add(new Series { ChartType = SeriesChartType.Line, Color = Color.DarkGray, Name = $"ExtremePointsLine{order}", YValuesPerPoint = 1, IsVisibleInLegend = false }); profileChart.Series[$"ExtremePointsLine{order}"].BorderDashStyle = ChartDashStyle.Dash; profileChart.Series[$"ExtremePointsLine{order}"].Points.AddXY(observerPoint.Distance, observerPoint.Z); profileChart.Series[$"ExtremePointsLine{order}"].Points[0].MarkerStyle = MarkerStyle.Circle; profileChart.Series[$"ExtremePointsLine{order}"].Points.AddXY(observationPoint.Distance, observationPoint.Z); if (profileChart.Series[$"{order}"].Points.Last().Color == profileChart.Series[$"{order}"].BackSecondaryColor) { profileChart.Series[$"ExtremePointsLine{order}"].Points[1].MarkerColor = Color.Red; } profileChart.Series[$"ExtremePointsLine{order}"].Points[1].MarkerStyle = MarkerStyle.Circle; }
private static double VectorCross(ProfileSurfacePoint leftPoint, ProfileSurfacePoint rightPoint) { return(leftPoint.Distance * rightPoint.Z - leftPoint.Z * rightPoint.Distance); }
private static double PointsProduct(ProfileSurfacePoint leftPoint, ProfileSurfacePoint rightPoint) { return(rightPoint.Distance * leftPoint.Distance + rightPoint.Z * leftPoint.Z); }
private static ProfileSurfacePoint PointsDiff(ProfileSurfacePoint leftPoint, ProfileSurfacePoint rightPoint) { return(new ProfileSurfacePoint { Distance = rightPoint.Distance - leftPoint.Distance, Z = rightPoint.Z - leftPoint.Z }); }
public ProfileSession GenerateProfile( string profileSource, IEnumerable <IPolyline> profileLines, ProfileSettingsTypeEnum profileSettingsTypeEnum, int sessionId, string sessionName, double observHeight, string azimuthes) { string profileSourceName = GdbAccess.Instance.AddProfileLinesToCalculation(profileLines); var action = new ActionParam <string>() { ParamName = ActionParamNamesCore.Action, Value = ActionsEnum.bsp.ToString() }; string sdtnow = MilSpace.DataAccess.Helper.GetTemporaryNameSuffix(); var resuTable = $"{MilSpaceConfiguration.ConnectionProperty.TemporaryGDBConnection}\\StackProfile{sdtnow}"; var profileLineFeatureClass = GdbAccess.Instance.GetProfileLinesFeatureClass(profileSourceName); var prm = new List <IActionParam> { action, new ActionParam <string>() { ParamName = ActionParameters.FeatureClass, Value = profileLineFeatureClass }, new ActionParam <string>() { ParamName = ActionParameters.ProfileSource, Value = profileSource }, new ActionParam <string>() { ParamName = ActionParameters.DataWorkSpace, Value = resuTable }, new ActionParam <string>() { ParamName = ActionParameters.OutGraphName, Value = "" } }; var procc = new ActionProcessor(prm); var res = procc.Process <BoolResult>(); if (!res.Result) { if (res.Exception != null) { throw res.Exception; } //TODO: Log error throw new Exception(res.ErrorMessage); } //Take the table and import the data ISpatialReference currentSpatialreference = profileLines.First().SpatialReference; try { string tempTableName = $"StackProfile{sdtnow}"; ITable profiletable = GdbAccess.Instance.GetProfileTable(tempTableName); IFeatureClass lines = GdbAccess.Instance.GetCalcProfileFeatureClass(profileSourceName); IQueryFilter queryFilter = new QueryFilter() { WhereClause = WhereAllRecords }; ICursor featureCursor = profiletable.Search(queryFilter, true); IRow profileRow; int distanceFld = profiletable.FindField(FIRST_DIST_Field); int zFld = profiletable.FindField(FIRST_Z_Field); int idFld = profiletable.FindField(LINE_ID_Field); List <ProfileSurface> profileSurfaces = new List <ProfileSurface>(); ProfileSession session = new ProfileSession() { ProfileSurfaces = profileSurfaces.ToArray(), ProfileLines = GetProfileLines(lines).ToArray(), SessionId = sessionId, SessionName = sessionName, DefinitionType = profileSettingsTypeEnum, ObserverHeight = observHeight, SurfaceLayerName = profileSource, CreatedBy = Environment.UserName, CreatedOn = DateTime.Now, Shared = false, Azimuth = azimuthes }; Dictionary <int, List <ProfileSurfacePoint> > surface = new Dictionary <int, List <ProfileSurfacePoint> >(); int curLine = -1; IPolyline line = null; IEnumerable <IPoint> verticesCache; Dictionary <IPoint, ProfileSurfacePoint> mapProfilePointToVertex = new Dictionary <IPoint, ProfileSurfacePoint>(); Dictionary <IPoint, double> mapProfilePointToDistance = new Dictionary <IPoint, double>(); ProfileLine profileLine = null; verticesCache = new IPoint[0]; int pointsCount = 0; while ((profileRow = featureCursor.NextRow()) != null) { int lineId = Convert.ToInt32(profileRow.Value[idFld]); pointsCount++; if (!session.ProfileLines.Any(l => l.Id == lineId)) { throw new MilSpaceProfileLineNotFound(lineId, profileLineFeatureClass); } List <ProfileSurfacePoint> points; if (!surface.ContainsKey(lineId)) { points = new List <ProfileSurfacePoint>(); surface.Add(lineId, points); } else { points = surface[lineId]; } if (curLine != lineId) // data for new line { curLine = lineId; profileLine = session.ProfileLines.FirstOrDefault(l => l.Id == lineId); line = lines.GetFeature(profileLine.Id).Shape as IPolyline; verticesCache = line.Vertices(); mapProfilePointToVertex.ToList().ForEach(v => { if (!v.Value.IsEmpty) { v.Value.isVertex = true; } }); mapProfilePointToVertex = verticesCache.ToDictionary(k => k, t => new ProfileSurfacePoint()); mapProfilePointToDistance = verticesCache.ToDictionary(k => k, t => - 1.0); } //Returns the point with Origin (Taken from firstPoint) Spatial reference //var profilePointSource = EsriTools.GetPointFromAngelAndDistance(firstPoint, profileLine.Angel, (double)profileRow.Value[distanceFld]); //var profilePoint = profilePointSource.CloneWithProjecting(); // Try to define if this point is close to a vertex double distance = (double)profileRow.Value[distanceFld]; ProfileSurfacePoint newSurface = new ProfileSurfacePoint { Distance = distance, Z = (double)profileRow.Value[zFld], //X = profilePoint.X, //Y = profilePoint.Y }; IPoint point = new Point(); line.QueryPoint(esriSegmentExtension.esriNoExtension, newSurface.Distance, false, point); IProximityOperator proximity = point as IProximityOperator; foreach (var vertx in verticesCache) { var profilePoint = mapProfilePointToVertex[vertx]; if (mapProfilePointToDistance[vertx] == 0)// profilePoint.isVertex) { continue; } double localDistance = proximity.ReturnDistance(vertx); if (mapProfilePointToDistance[vertx] == -1 || mapProfilePointToDistance[vertx] > localDistance) { mapProfilePointToDistance[vertx] = localDistance; mapProfilePointToVertex[vertx] = newSurface; if (localDistance == 0) { newSurface.isVertex = true; } } } var projected = point.CloneWithProjecting(); newSurface.X = projected.X; newSurface.Y = projected.Y; points.Add(newSurface); } mapProfilePointToVertex.ToList().ForEach(v => { if (!v.Value.IsEmpty) { v.Value.isVertex = true; } }); //Delete temp table form the GDB GdbAccess.Instance.DeleteTemporarSource(tempTableName, profileSourceName); Marshal.ReleaseComObject(featureCursor); //TODO: Clean memo using Marhsaling IRow session.ProfileSurfaces = surface.Select(r => new ProfileSurface { LineId = r.Key, ProfileSurfacePoints = r.Value.ToArray() } ).ToArray(); return(session); } catch (MilSpaceCanotDeletePrifileCalcTable ex) { //TODO: Log error throw ex; } catch (MilSpaceDataException ex) { //TODO: Log error throw ex; } catch (Exception ex) { //TODO: Log error throw ex; } }