Hi,
I could use some help with the count function. I have routine that will add the sum of all lengths and create a list by entity type with the total length of each object. I am trying to add the counted number of said object to the output. But I am getting "wacky" results. My code below shows how I am currently to it. I would like to know how polylines, arcs, circles, etc. where used to calculate the total length of each.
Current Output:
3D Polyline(s) = 39.3321
Spline(s) = 15.4985
2D Polyline(s) = 4.7934
Ellipse(s) = 5.8078
Arc(s) = 5.5853
Circle(s) = 10.281
Polyline(s) = 9.1494
Total Length of all Objects Combined:
90.4474
Trying to Achive:
(1) 3D Polyline(s) = 39.3321
(1) Spline(s) = 15.4985
(2) 2D Polyline(s) = 4.7934
(1) Ellipse(s) = 5.8078
(3) Arc(s) = 5.5853
(2) Circle(s) = 10.281
(10) Polyline(s) = 9.1494
Total Length of all Objects Combined:
90.4474
... If selectAllResults.Status <> PromptStatus.OK Then Return Dim lengthes = selectAllResults.Value.Cast(Of SelectedObject)().[Select](Function(so) CType(acTrans.GetObject(so.ObjectId, OpenMode.ForRead), Curve)).ToLookup(Function(curve) curve.[GetType]().Name, Function(curve) curve.GetDistanceAtParameter(curve.EndParam)).ToDictionary(Function(group) group.Key, Function(group) group.Sum()) Dim entryList As New List(Of String) For Each entry In lengthes Dim roundedValue = Math.Round(entry.Value, 4) If entry.Key.ToString = "Polyline2d" Then Dim replacedName = entry.Key.Replace("Polyline2d", "2D Polyline(s)") entryList.Add($"({entry.Key.Count}) {replacedName} = {roundedValue}" & vbLf) ElseIf entry.Key.ToString = "Polyline3d" Then Dim replacedName = entry.Key.Replace("Polyline3d", "3D Polyline(s)") entryList.Add($"({entry.Key.Count}) {replacedName} = {roundedValue}" & vbLf) Else entryList.Add($"({entry.Key.Count}) {entry.Key}(s) = {roundedValue}" & vbLf) End If Next Dim compiledList As String = String.Join("", entryList) ...
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Hi,
You should build your string within the Linq query, just after the GroupBy call so that you can still acces to the entities count and compute the lengthes sum.
selectAllResults.Value .Cast<SelectedObject>() .Select(so => (Curve)acTrans.GetObject(so.ObjectId, OpenMode.ForRead)) .GroupBy(c => c.GetType().Name) .Select(g => string.Format("({0}) {1} = {2}", g.Count(), g.Key, g.Sum(c => Math.Round(c.GetDistanceAtParameter(c.EndParam), 4))));
Thank you yet again. I really appreciate it. This defiantly made it easier.
One last thing. I am now having a hard time getting the total of all objects together. Now that the variable is as IEnumerable vs Dictionary I do not know how to get the total of all objects. Any help would be greatly appreciated. Updated code below:
... If selectAllResults.Status <> PromptStatus.OK Then Return Dim lengthes = selectAllResults.Value.Cast(Of SelectedObject)().[Select](Function(so) CType(acTrans.GetObject(so.ObjectId, OpenMode.ForRead), Curve)).GroupBy(Function(c) c.[GetType]().Name).[Select](Function(g) String.Format("({0}) {1}{2} = {3}", g.Count(), g.Key, (If(g.Count = 1, "", "s")), g.Sum(Function(c) Math.Round(c.GetDistanceAtParameter(c.EndParam), 4)))) Dim entryList As New List(Of String) For Each entry In lengthes If entry.ToString.Contains("Polyline2d") Then Dim replacedName = entry.Replace("Polyline2d", "2D Polyline") entryList.Add($"{replacedName}" & vbLf) ElseIf entry.ToString.Contains("Polyline3d") Then Dim replacedName = entry.Replace("Polyline3d", "3D Polyline") entryList.Add($"{replacedName}" & vbLf) Else entryList.Add($"{entry}" & vbLf) End If Next Dim compiledList As String = String.Join("", entryList) ...
You can use an anonymous type (VB) to store the data and the consume them as needed.
var curves = selectAllResults.Value .Cast<SelectedObject>() .Select(so => (Curve)acTrans.GetObject(so.ObjectId, OpenMode.ForRead)) .GroupBy(c => c.GetType().Name) .Select(g => new { Name = g.Key, Count = g.Count(), Length = g.Sum(c => c.GetDistanceAtParameter(c.EndParam)) }); double totalLength = curves.Sum(x => x.Length); string[] lengthes = curves .Select(x => string.Format("({0} {1} = {2}", x.Count, x.Name, Math.Round(x.Length, 4))) .ToArray();
I see what you did, and it makes a lot of sense. I really like that approach, because as you said you can store them and use them as needed in almost any fashion. It's a nice way to be able to retrieve pieces or the all at once. I also appreciate the link to info on anonymous types. It helped close the loop on what you did.
As always, thank you very much!
Completed Code for anyone else looking:
... If selectAllResults.Status <> PromptStatus.OK Then Return Dim curves = selectAllResults.Value _ .Cast(Of SelectedObject)() _ .[Select](Function(so) CType(acTrans.GetObject(so.ObjectId, OpenMode.ForRead), Curve)) _ .GroupBy(Function(c) c.[GetType]().Name) _ .[Select](Function(g) New With {Key .Name = g.Key, Key .Count = g.Count(), Key .Length = g.Sum(Function(c) c.GetDistanceAtParameter(c.EndParam))}) Dim lengthes As String() = curves.[Select](Function(x) String.Format("({0}) {1}{2} = {3}", x.Count, x.Name, (If(x.Count = 1, "", "s")), Math.Round(x.Length, 4))).ToArray() Dim totalLength As Double = curves.Sum(Function(x) Math.Round(x.Length, 4)) Dim entryList As New List(Of String) For Each entry In lengthes If entry.ToString.Contains("Polyline2d") Then Dim replacedName = entry.Replace("Polyline2d", "2D Polyline") entryList.Add($"{replacedName}" & vbLf) ElseIf entry.ToString.Contains("Polyline3d") Then Dim replacedName = entry.Replace("Polyline3d", "3D Polyline") entryList.Add($"{replacedName}" & vbLf) Else entryList.Add($"{entry}" & vbLf) End If Next Dim compiledList As String = String.Join("", entryList) ....
Can't find what you're looking for? Ask the community or share your knowledge.