Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Help with Count Function

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
David_Prontnicki
420 Views, 4 Replies

Help with Count Function

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)
...

 

4 REPLIES 4
Message 2 of 5
_gile
in reply to: David_Prontnicki

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))));


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 5
David_Prontnicki
in reply to: _gile

@_gile 

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)
...
Message 4 of 5
_gile
in reply to: David_Prontnicki

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();

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 5
David_Prontnicki
in reply to: _gile

@_gile 

 

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.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report