using System.Xml.Serialization; namespace ShrlAlgoToolkit.RevitAddins.RvIndependent.MetroGauges.LandXMLData; [XmlType("Alignment")] [Serializable] public class Alignment : ComparableStructure { public Alignment() { Init(); } public Alignment(Alignment alignment) { if (alignment != null) { Id = alignment.Id; Description = alignment.Description; Name = alignment.Name; StationStart = alignment.StationStart; StationEnd = alignment.StationEnd; Length = alignment.Length; CoordGeom = alignment.CoordGeom; Regions = alignment.Regions; FeatureLines = alignment.FeatureLines; CrossSections = alignment.CrossSections; Profile = alignment.Profile; SuperElevations = alignment.SuperElevations; Structres = alignment.Structres; Import = alignment.Import; geometricCenter = alignment.geometricCenter; return; } Init(); } private string description; private Point3D geometricCenter; private string id; private string name; [XmlIgnore] public Point3D GeometricCenter { get { if (geometricCenter == null) { SetGeometricCenter(); } return geometricCenter; } set => geometricCenter = null; } [Obsolete("Property \"GetGeometricCenter\" is deprecated, please use \"GeometricCenter\" instead.")] [XmlIgnore] public Point3D GetGeometricCenter => GeometricCenter; [XmlIgnore] public ProfAlign GroundProfile => Profile.ProfileCurve.Find(item => item.Type == 0) ?? Profile.ProfileCurve.FirstOrDefault(); [XmlIgnore] public IEnumerable PointCodes => CrossSections.SelectMany(item => item.PointCodes); [XmlIgnore] public IEnumerable SurfaceNames => CrossSections.SelectMany(item => item.SurfaceNames); [XmlIgnore] public ProfAlign WayProfile { get { ProfAlign result; if ((result = Profile.ProfileCurve.Find(item => item.Type == 1)) == null) { result = Profile.ProfileCurve.Find(item => item.Type == 2) ?? Profile.ProfileCurve.FirstOrDefault(); } return result; } } [XmlAttribute("desc")] public string Description { get => description; set => description = value; } [XmlAttribute("AlignmentID")] public string Id { get => id; set => id = value; } [XmlAttribute("name")] public string Name { get => name; set => name = value; } [XmlIgnore] internal string AlignmentId => (Roadway != null ? Roadway.CorridorID : string.Empty) + Id; [XmlAttribute("import")] public bool Import { get; set; } [XmlElement("CoordGeom")] public CoordGeom CoordGeom { get; set; } [XmlAttribute("staStart")] public double StationStart { get; set; } [XmlAttribute("staEnd")] public double StationEnd { get; set; } [XmlAttribute("length")] public double Length { get; set; } [XmlArray("CrossSects")] public List CrossSections { get; set; } [XmlArray("FeatureLines")] public List FeatureLines { get; set; } [XmlArray("Regions")] public List Regions { get; set; } [XmlArray("Structures")] public List Structres { get; set; } [XmlElement("Profile")] public Profile Profile { get; set; } [XmlElement("Superelevation")] public List SuperElevations { get; set; } [XmlIgnore] public Roadway Roadway { get; set; } public void AddRegion(Region region) { Regions.Add(region); region.Alignment = this; } public void ConnectRegions() { foreach (var region in Regions) { region.Alignment = this; } } public void ConnectSectionsShape(DesignShape linkShape, DesignShape refShape, CrossSection section, CrossSection refSection = null) { var num = 0; linkShape.CrossSectionPoints.Clear(); var array = (from ds in section.DesignShapes where ds.Name == refShape.Name && ds.Side == refShape.Side select ds) .SelectMany(ds => ds.CrossSectionPoints) .ToArray(); var list = !(refSection != null) ? new List() : (from ds in refSection.DesignShapes where ds.Name == refShape.Name && ds.Side == refShape.Side select ds) .SelectMany(ds => ds.CrossSectionPoints) .ToList(); var list2 = list; using (var enumerator = refShape.CrossSectionPoints.GetEnumerator()) { while (enumerator.MoveNext()) { var point = enumerator.Current; var crossSectionPoint = array.FirstOrDefault(p => p.Code == point?.Code); if (crossSectionPoint != null) { linkShape.CrossSectionPoints.Add(new CrossSectionPoint(crossSectionPoint)); } else { var num2 = list2.IndexOf(point); if (num2 >= 0) { num = num2; } CrossSectionPoint crossSectionPoint2 = new(num < array.Length ? array[num] : array.Last()) { Code = point?.Code }; linkShape.CrossSectionPoints.Add(crossSectionPoint2); } num++; } } linkShape.UpdatePointDependentData(); section.DesignShapes.Add(linkShape); } public override bool DifferentDescendants(Alignment alignment) { if (Regions.Count == alignment.Regions.Count) { for (var i = 0; i < Regions.Count; i++) { if (!Regions[i].Equals(alignment.Regions[i])) { return true; } } return false; } return true; } public override bool DifferentItem(Alignment alignment) { return StationStart != alignment.StationStart || StationEnd != alignment.StationEnd || GeometricCenter != alignment.GeometricCenter; } public Region FindRegion(Region reference) { return Regions.FirstOrDefault(item => item.Name == reference.Name); } public Point3D GeometricCenterInRange(double startStation, double endStation) { var array = (from item in CrossSections where item.Station >= startStation && item.Station <= endStation select item).ToArray(); return CalcGeometricCenter(array, array.Length); } public double GetAzimuthAtStation(double station) { var num = 0.0; var num2 = 0.0; foreach (var interval in CoordGeom.HorizonCurve) { if (num + interval.Length >= station) { num2 += interval.GetDirectionAtPoint(station - num); break; } num2 += interval.GetDirectionAtPoint(interval.Length); num += interval.Length; } return num2; } //直线 public double GetHeightAtStation(double station) { var result = 0.0; var profAlign = Profile.ProfileCurve.FirstOrDefault(item => item.Type == 2); if (profAlign != null) { var num = profAlign.PVIs.Count - 1; var i = 0; while (i < num) { if (profAlign.PVIs[i].First >= station) { if (profAlign.PVIs[i] is not ParaCurve && profAlign.PVIs[i + 1] is not ParaCurve) { result = profAlign.PVIs[i].Second + ( (station - profAlign.PVIs[i].First) * (profAlign.PVIs[i + 1].Second - profAlign.PVIs[i].Second) / (profAlign.PVIs[i + 1].First - profAlign.PVIs[i].First) ); } break; } i++; } } return result; } public IEnumerable GetPointCodes(Side side, int region = -1) { return region >= 0 ? side != Side.Both ? (from item in CrossSections where item.Region == region select item).SelectMany(item => item.GetPointCodes(side)).Distinct() : (from item in CrossSections where item.Region == region select item).SelectMany(item => item.PointCodes).Distinct() : side != Side.Both ? CrossSections.SelectMany(item => item.GetPointCodes(side)).Distinct() : PointCodes.Distinct(); } public void Initialize(string n, double s, double e, double l, string id, string d) { Name = n; StationStart = s; StationEnd = e; Length = l; Id = id; Description = d; } public void RefreshShapes() { } public void RemoveRegion(Region region) { if (Regions.Remove(region)) { region.Alignment = null; } } public void RemoveSameSections() { for (var i = CrossSections.Count - 1; i > 0; i--) { if (CrossSections[i - 1].Station == CrossSections[i].Station) { CrossSections.RemoveAt(i); } } GeometricCenter = null; } public void ResetImportsAndParts() { try { Import = true; foreach (var crossSection in CrossSections) { crossSection.Import = true; foreach (var designShape in crossSection.DesignShapes) { designShape.Import = true; designShape.Part = 0; } for (var i = crossSection.DesignShapes.Count - 1; i >= 0; i--) { var shape = crossSection.DesignShapes[i]; if (crossSection.DesignShapes.Count(ds => ds.NameSide == shape.NameSide) > 1) { if (shape.CrossSectionPoints.Count < crossSection.DesignShapes.Max(ds => ds.CrossSectionPoints.Count)) { crossSection.DesignShapes.RemoveAt(i); } } } } } catch { // ignored } } public void SplitDifferentParts() { try { var crossSection = CrossSections.Count > 0 ? CrossSections[0] : null; for (var i = 1; i < CrossSections.Count; i++) { var crossSection2 = CrossSections[i]; if (crossSection2.Import) { var count = crossSection2.DesignShapes.Count; for (var j = 0; j < count; j++) { var shape = crossSection2.DesignShapes[j]; var pointCodesFlat = shape.PointCodesFlat; var designShape = crossSection.DesignShapes.FirstOrDefault(ds => ds.NameSideSegment == shape.NameSideSegment); var flag4 = !crossSection.Import; var flag5 = designShape != null && designShape.PointCodesFlat != pointCodesFlat && crossSection2.Station != crossSection.Station; if (designShape == null || !designShape.Import || flag5 || crossSection2.Region != crossSection.Region) { flag4 = shape.Import; if (flag5) { if (shape.Import && crossSection.DesignShapes.Count < crossSection2.DesignShapes.Count) { ConnectSectionsShape(new DesignShape(designShape) { Import = false }, designShape, crossSection2, crossSection); } else if (designShape.Import) { DesignShape designShape2 = new(shape) { Import = true }; ConnectSectionsShape(designShape2, shape, crossSection, crossSection2); AddRange(crossSection2, shape, i); designShape2.Part = i; } } } if (!crossSection.Import) { AddRange(crossSection2, shape, i); for (var k = i + 1; k < CrossSections.Count; k++) { var designShape3 = CrossSections[k].DesignShapes.FirstOrDefault(ds => ds.NameSideSegment == shape.NameSideSegment); if (designShape3 != null) { designShape3.Part = i; } } shape.Part = i; } } } crossSection = crossSection2; } } catch { // ignored } } public void Transform(GeometryTransformations transformations) { foreach (var interval in CoordGeom.HorizonCurve) { interval.Transform(transformations); } StationStart *= transformations.ScaleFactor; StationEnd *= transformations.ScaleFactor; foreach (var region in Regions) { region.StartStation *= transformations.ScaleFactor; region.EndStation *= transformations.ScaleFactor; } foreach (var crossSection in CrossSections) { crossSection.Transform(transformations); } foreach (var profAlign in Profile.ProfileCurve) { profAlign.Transform(transformations); } GeometricCenter = null; } public void TransformByScale(double scale) { var point3D = GeometricCenter; var flag = point3D.LengthSquared3D != 0.0; GeometryTransformations geometryTransformations = new(); if (flag) { geometryTransformations.Translation(-point3D.X, -point3D.Y, -point3D.Z); } geometryTransformations.Scale(scale); point3D *= scale; if (flag) { geometryTransformations.Translation(point3D.X, point3D.Y, point3D.Z); } Transform(geometryTransformations); } protected void AddRange(Part part, double start, double end, int i) { Range range = new() { Part = i }; range.SetRange(start, end); part.AddRange(range); } protected Point3D CalcGeometricCenter(IEnumerable sections, int count) { Point3D point3D = new(); if (count != 0) { foreach (var p in sections) { point3D += p / count; } } return point3D; } protected void SetGeometricCenter() { if (CrossSections != null) { geometricCenter = CalcGeometricCenter(CrossSections, CrossSections.Count); return; } geometricCenter = new Point3D(); } internal void AddRange(CrossSection section, DesignShape shape, int i) { var region = Regions.FirstOrDefault(item => item.Id == section.Region); if (region != null) { var part = region.Parts.FirstOrDefault(item => item.NameSideSegment == shape.NameSideSegment); var endStation = part.Ranges.Last().EndStation; if (section.Station > endStation) { AddRange(part, endStation, section.Station, i); return; } if (section.Station != endStation) { var startStation = part.Ranges.First().StartStation; if (section.Station < startStation) { AddRange(part, section.Station, startStation, i); return; } if (section.Station != startStation) { part.Ranges.Last().EndStation = section.Station; AddRange(part, section.Station, endStation, i); } } } } private void Init() { CrossSections = new List(); FeatureLines = new List(); Regions = new List(); SuperElevations = new List(); CoordGeom = new CoordGeom(); Profile = new Profile(); geometricCenter = null; Import = true; } }