using System.Xml.Serialization; using ShrlAlgoToolkit.RevitAddins.RvIndependent.MetroGauges.LandXMLData.Interfaces; namespace ShrlAlgoToolkit.RevitAddins.RvIndependent.MetroGauges.LandXMLData; [XmlType("DesignCrossSectSurf")] [Serializable] public class DesignShape : ObjectWithNameSideSegmentPart, IComparableStructure { public DesignShape() { CrossSectionPoints = new List(); Import = true; } public DesignShape(DesignShape refShape) : base(refShape) { CrossSectionPoints = new List(refShape.CrossSectionPoints); SurfaceID = refShape.SurfaceID; Area = refShape.Area; ClosedArea = refShape.ClosedArea; BorderColorARGB = refShape.BorderColorARGB; FillColorARGB = refShape.FillColorARGB; Import = refShape.Import; } public CrossSectionPoint this[int index] { get { return index < CrossSectionPoints.Count ? CrossSectionPoints[index] : throw new IndexOutOfRangeException(); } set { if (index < CrossSectionPoints.Count) { CrossSectionPoints[index] = value; return; } if (index == CrossSectionPoints.Count) { CrossSectionPoints.Add(value); return; } throw new IndexOutOfRangeException(); } } public int Count => CrossSectionPoints.Count; public bool IsReadOnly => false; [XmlIgnore] public IEnumerable PointCodes => from item in CrossSectionPoints select item.Code; [XmlIgnore] public string PointCodesFlat { get { var text = string.Empty; foreach (var str in PointCodes) { text = text + str + " "; } return text; } } [XmlIgnore] public double Station { get { return CrossSection == null ? double.NaN : CrossSection.Station; } } [XmlAttribute("closedArea")] public bool ClosedArea { get; set; } [XmlAttribute("import")] public bool Import { get; set; } [XmlIgnore] public CrossSection CrossSection { get; internal set; } [XmlAttribute("area")] public double Area { get; set; } [XmlAttribute("bARGB")] public int BorderColorARGB { get; set; } [XmlAttribute("fARGB")] public int FillColorARGB { get; set; } [XmlElement("CrossSectPnt")] public List CrossSectionPoints { get; set; } [XmlAttribute("surfID")] public string SurfaceID { get; set; } public bool DifferentDescendants(DesignShape shape) { if (CrossSectionPoints.Count == shape.CrossSectionPoints.Count) { for (var i = 0; i < CrossSectionPoints.Count; i++) { if (!CrossSectionPoints[i].Equals(shape.CrossSectionPoints[i])) { return true; } } return false; } return true; } public bool DifferentItem(DesignShape shape) { return Station != shape.Station || Area != shape.Area; } public bool Equals(DesignShape shape) { return !ReferenceEquals(shape, null) && !DifferentItem(shape) && !DifferentDescendants(shape); } public void Add(CrossSectionPoint item) { CrossSectionPoints.Add(item); } public void Clear() { CrossSectionPoints.Clear(); } public bool Contains(CrossSectionPoint item) { return CrossSectionPoints.Contains(item); } public void CopyTo(CrossSectionPoint[] array, int arrayIndex) { CrossSectionPoints.CopyTo(array, arrayIndex); } public override bool Equals(object obj) { return Equals(obj as DesignShape); } public IEnumerator GetEnumerator() { return CrossSectionPoints.GetEnumerator(); } public override int GetHashCode() { return base.GetHashCode(); } public IEnumerable GetPointCodes(Side side) { if (side == Side.Left) { return (from item in CrossSectionPoints where item.First <= 0.0 select item.Code).Distinct(); } return side == Side.Right ? (from item in CrossSectionPoints where item.First >= 0.0 select item.Code).Distinct() : PointCodes.Distinct(); } public int IndexOf(CrossSectionPoint item) { return CrossSectionPoints.IndexOf(item); } public void Insert(int index, CrossSectionPoint item) { CrossSectionPoints.Insert(index, item); } public bool NameSideEquals(DesignShape ds) { return ds.Name == Name && ds.Part == Part && ds.Side == Side; } public bool NameSideSegmentEquals(DesignShape ds) { return NameSideEquals(ds) && ds.Segment == Segment; } public bool Remove(CrossSectionPoint item) { return CrossSectionPoints.Remove(item); } public void RemoveAt(int index) { CrossSectionPoints.RemoveAt(index); } public void SetArea() { Area = 0.0; if (ClosedArea) { var num = CrossSectionPoints.LastIndexOf(CrossSectionPoints[0]) + 1; for (var i = 0; i < num; i++) { var index = (i + 1) % num; Area += (CrossSectionPoints[i].First * CrossSectionPoints[index].Second) - (CrossSectionPoints[index].First * CrossSectionPoints[i].Second); } Area /= 2.0; } } public bool SetClosedArea() { return CrossSectionPoints.Count > 3 ? (ClosedArea = CrossSectionPoints.LastIndexOf(CrossSectionPoints[0]) > 0) : (ClosedArea = false); } public void SetSegment(CrossSection thisSection, CrossSection prevSection) { var flag = true; if (prevSection != null) { var pcf = PointCodesFlat; Segment = thisSection.DesignShapes.Count(ds => ds.NameSideEquals(this)); var designShape = ( from ds in prevSection.DesignShapes where ds.NameSideEquals(this) && ds.PointCodesFlat == pcf orderby Math.Abs(ds.Segment - Segment) select ds ).FirstOrDefault(); if (designShape != null) { Segment = designShape.Segment; flag = false; } } if (flag || thisSection.DesignShapes.Count(ds => ds.NameSideSegmentEquals(this)) > 0) { Segment = thisSection.DesignShapes.Count(ds => ds.NameSideEquals(this)); } } public void SetSide() { if (Count > 0) { Side side; if (CrossSectionPoints.Count(p => p.First == 0.0) != Count) { side = CrossSectionPoints.Max(p => p.First) > 0.0 ? CrossSectionPoints.Min(p => p.First) >= 0.0 ? Side.Right : Side.Both : Side.Left; } else { side = Side.Both; } Side = side; } } public void Transform(GeometryTransformations transformations) { foreach (var crossSectionPoint in CrossSectionPoints) { crossSectionPoint.Transform(transformations, false); } } public void UpdatePointDependentData() { SetSide(); SetClosedArea(); SetArea(); } }