Ad

Sunday, September 27, 2020

Corridor Surface Shrink

This post is in regard to this Civil 3D Idea: 

https://forums.autodesk.com/t5/civil-3d-ideas/corridor-boundaries/idi-p/5908587

This post will provide a workflow to programmatically delete tin triangles outside of the corridor. 

This code deletes triangles, but it could be modified to add the polylines as boundaries instead of going through the triangles that are outside of the corridor.

It's not full proof, but it's intended to quickly get triangles that are outside of the corridor for design purposes.

The MPolygon requires a reference to this dll: 

C:\Program Files\Autodesk\AutoCAD 2021\AcMPolygonMGD.dll

    public class CorridorShrinkwrap
    {
        [CommandMethod("CorridorShrinkwrap")]
        public void CorridorShrinkwrapCommand()
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            var ed = doc.Editor;
            var db = doc.Database;

            try
            {
                using (var tr = doc.TransactionManager.StartTransaction())
                using (var btr = db.CurrentSpaceId.GetObject(OpenMode.ForWrite) as BlockTableRecord)
                {
                    var corridorTypVals = new List<TypedValue>
                            {
                                new TypedValue((int)DxfCode.Operator, "<OR"),
                                new TypedValue((int)DxfCode.Start, RXClass.GetClass(typeof(Corridor)).DxfName),
                                new TypedValue((int)DxfCode.Operator, "OR>")
                            };

                    var corrObjIds = ed.GetEntities(corridorTypVals, "\nSelect corridor: ", "\nSelection objects to remove",
                                                     out List<FullSubentityPath> xrefPaths);

                    if (!corrObjIds.Any())
                    {
                        return;
                    }

                    ed.UnHighlightSelectedXREFSubEntities(xrefPaths);

                    var strRslt = ed.GetString("\nEnter link code to shrink to: ");

                    if (strRslt.Status != Autodesk.AutoCAD.EditorInput.PromptStatus.OK)
                    {
                        return;
                    }

                    var code = strRslt.StringResult;
                    var tolerance = Tolerance.Global.EqualPoint;

                    foreach (var corrObjId in corrObjIds)
                    {
                        var corr = corrObjId.GetObject(OpenMode.ForWrite) as Corridor;
                        var polylines = new List<Polyline>();
                        var mpolys = new List<MPolygon>();
                        foreach (var baseline in corr.Baselines)
                        {
                            foreach (var region in baseline.BaselineRegions)
                            {
                                var polyPts = new List<Tuple<ObjectId, CalculatedPoint, CalculatedPoint>>();

                                foreach (var assembly in region.AppliedAssemblies)
                                {                                    
                                    foreach (var subAss in assembly.GetAppliedSubassemblies())
                                    {
                                        var links = subAss.Links.Where(x => x.CorridorCodes.Contains(code));
                                        if (!links.Any())
                                        {
                                            continue;
                                        }
                                        var linkPoints = links.SelectMany(x => x.CalculatedPoints.Select(y => y)).OrderBy(z => z.StationOffsetElevationToBaseline.Y).ToList();
                                        polyPts.Add(new Tuple<ObjectId, CalculatedPoint, CalculatedPoint>(subAss.SubassemblyId, linkPoints.First(), linkPoints.Last()));
                                    }
                                }

                                // Collect the points by subassembly.
                                var polyInfos = polyPts.GroupBy(x => x.Item1).ToDictionary(x => x.Key, x => x.OrderBy(y => y.Item2.StationOffsetElevationToBaseline.X).ToList());

                                foreach (var kvp in polyInfos)
                                {
                                    var poly = new Polyline();

                                    foreach (var pt in kvp.Value)
                                    {
                                        poly.AddVertexAt(poly.NumberOfVertices, pt.Item2.XYZ.ToPoint2d(), 0, 0, 0);
                                    }

                                    kvp.Value.Reverse();
                                    
                                    foreach (var pt in kvp.Value)
                                    {
                                        poly.AddVertexAt(poly.NumberOfVertices, pt.Item3.XYZ.ToPoint2d(), 0, 0, 0);
                                    }

                                    poly.Closed = true;

                                    var plObjId = btr.AppendEntity(poly);
                                    tr.AddNewlyCreatedDBObject(poly, true);

                                    polylines.Add(poly);

                                    var mPoly = new MPolygon();
                                    mPoly.AppendLoopFromBoundary(poly, true, tolerance);

                                    mpolys.Add(mPoly);
                                }

                                // find the surfaces that contain the code. 
                                foreach (var corrSurf in corr.CorridorSurfaces.Where(x => x.LinkCodes().Contains(code)))
                                {
                                    var edgesToDelete = new List<TinSurfaceEdge>();
                                    var corrTinSurf = corrSurf.SurfaceId.GetObject(OpenMode.ForWrite) as TinSurface;
                                    foreach (var tinEdge in corrTinSurf.Triangles.SelectMany(x => new List<TinSurfaceEdge> { x.Edge1, x.Edge2, x.Edge3 }).Distinct())
                                    {
                                        using (var tempLine = new Line(tinEdge.Vertex1.Location, tinEdge.Vertex2.Location))
                                        {
                                            var midPt = tempLine.GetPointAtParameter((tempLine.EndParam - tempLine.StartParam) / 2);
                                            if (mpolys.Where(x => x.IsPointInsideMPolygon(midPt, tolerance).Count == 1).Any())
                                            {
                                                continue;
                                            }
                                            edgesToDelete.Add(tinEdge);
                                        }
                                    }

                                    if (!edgesToDelete.Any())
                                    {
                                        continue;
                                    }
                                    corrTinSurf.DeleteLines(edgesToDelete);
                                }
                            }
                        }

                        // dispose of the polylines. 
                        foreach (var poly in polylines)
                        {
                            poly.Dispose();
                        }

                        foreach (var mPoly in mpolys)
                        {
                            mPoly.Dispose();
                        }
                    }

                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: " + ex.Message);
            }
        }
    }

Corridor Gaps

Civil 3D doesn't always build every corridor section you might need. This is because where regions meet, if they have nearly the same station, then it won't draw the first section in the next region. To get a section at the adjacent regions you need to add a gap. This can be troublesome if you have lots of regions. The code below will prompt a user to select a corridor, enter a minimum gap distance, and then if the existing gap is less than the entered value the start station is modified to get the minimum gap. If the existing gap is larger than the minimum value then no change is made.

The code could be changed to save the last entered value and then make it the default value. This code can be found by using your favorite search engine.

Feel free to use this code. 

    public class CorridorGaps
    {
        [CommandMethod("MinimumCorridorGaps")]
        public void MinimumCorridorGapsCommand()
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            var ed = doc.Editor;

            try
            {
                using (var tr = doc.TransactionManager.StartTransaction())
                {
                    var corridorTypVals = new List<TypedValue>
                            {
                                new TypedValue((int)DxfCode.Operator, "<OR"),
                                new TypedValue((int)DxfCode.Start, RXClass.GetClass(typeof(Corridor)).DxfName),
                                new TypedValue((int)DxfCode.Operator, "OR>")
                            };

                    var corrObjIds = ed.GetEntities(corridorTypVals, "\nSelect corridor: ", "\nSelection objects to remove",
                                                     out List<FullSubentityPath> xrefPaths);

                    if (!corrObjIds.Any())
                    {
                        return;
                    }

                    ed.UnHighlightSelectedXREFSubEntities(xrefPaths);

                    var distRslt = ed.GetDistance("\nEnter minimum gap distance: ");

                    if (distRslt.Status != Autodesk.AutoCAD.EditorInput.PromptStatus.OK)
                    {
                        return;
                    }

                    var minGapDist = distRslt.Value;

                    foreach (var corrObjId in corrObjIds)
                    {
                        var corr = corrObjId.GetObject(OpenMode.ForWrite) as Corridor;
                        foreach (var baseline in corr.Baselines)
                        {
                            var lastRegionStation = double.NaN;
                            var baselineCount = baseline.BaselineRegions.Count;
                            for (int i = 0; i < baselineCount; i++)
                            {
                                if (i == 0)
                                {
                                    lastRegionStation = baseline.BaselineRegions[i].EndStation;
                                }
                                else
                                {
                                    var currentRegionStation = baseline.BaselineRegions[i].StartStation;
                                    var currentGap = currentRegionStation - lastRegionStation;
                                    if (currentGap < minGapDist)
                                    {
                                        baseline.BaselineRegions[i].StartStation = lastRegionStation + minGapDist;
                                    }
                                    lastRegionStation = baseline.BaselineRegions[i].EndStation;
                                }                                
                            }
                        }                        
                    }

                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: " + ex.Message);
            }
        }

Sunday, August 23, 2020

Autodesk Doesn't Care About Civil 3D

 Autodesk recently released Project Explorer for Civil 3D. Project Explorer is adequately named in that it only works with Civil 3D and no other Autodesk products. Instead of adding value to Civil 3D subscribers, Autodesk has decided to once again give the middle finger to Civil 3D subscribers and added the purchase to the AEC Collection instead of the Civil 3D subscription. The only product Project Explorer for Civil 3D works within the AEC Collection is Civil 3D. There seems to be no logical reason to add it to the AEC Collection only. 

I'm finding very little value across the AEC Collection since all I would use it for would be to access Civil 3D. I find InfraSucks a horrible product and Revit isn't of much use since I don't design buildings.

A subscription benefit is supposed to "Get instant access to the latest releases and enhancements." 


I'm not seeing the disclaimer of "...unless you subscribe to Civil 3D". So why isn't Autodesk providing Project Explorer for Civil 3D to Civil 3D Subscribers? 

For this reason, I'm officially telling people not to use or purchase Civil 3D or the AEC Collection. Autodesk doesn't care about you, and this adds to my existing long list of reasons. Find a different software provider that wants to give you value for the products you are paying for instead of taking your money, putting the money into different software, and then come back and tell you you have to pay more to get what you've already paid for. Autodesk isn't delivering on their promise of access to the latest releases and enhancements, so don't deliver your money to Autodesk. 

Thursday, July 16, 2020

Misc. Information

Add or Remove Ribbon Tabs

Easy Way

  • Right click on a Ribbon Tab. 
  • Choose Show Tabs, select the missing Tab

Hard Way (If the Tab is Missing Completely)

  • Type CUI at the command line. 
  • Select the Workspace to Edit on the Left. 
  • Press Customize Workspace.
  • Select the missing tab from the right side or upper main cui file or in a partial Customization Files below.
Right Click Shortcut Menus Missing
If your right click menu is missing, it can be reenabled by following the steps. 
  • Type OPTIONS at the command line. 
  • Go to the User Options tab. 
  • Make sure the “Shortcut menus in drawing area” is checked. 
  • Click the Right-click Customization Button. 
  • Uncheck the “Turn on time-sensitive right click” and make sure the remaining items are use the “Shortcut Menu” option.
Note that the time-sensitive right click can be useful to have enter as a quick right click and holding the right mouse button will show the desired Shortcut Menu. Sometimes reducing the duration is what is needed to make this a more user friendly option (125 milliseconds tends to work well).
Editing PGP File
The first step is to find the appropriate PGP file. To do so you can copy and pate the following line to the command line and press Enter. 
(findfile "acad.pgp")
This will let you know the command alias file that is currently being used. 
If one copies the path given, remove the duplicate “\”s.
The file may be opened in a Text Editor to be edited or the Express Tools => Command Aliases may be used to modify the file in a dialog box. 
PickAdd
The PickAdd variable toggles how objects are selected. 
  • If PickAdd is set to 0 then to select multiple objects the SHIFT key needs to be held down while selecting objects. 
  • If PickAdd is set to 1 then selected objects are added to the collection without holding down the SHIFT Key, but to unselect objects the ESC Key needs to be pressed.
I like using the SHIFT to select option since I don’t have to press ESC as much. To delesect an object all I need to do is make an empty selection.
If you are stuck using RDS through a browser I’d suggest having PickAdd set to 0 since if you have the browser full screen the escape key will force the browser to exit full screen. 
DDEDIT (Deprecated)
In recent releases Autodesk has deprecated DDEDIT and has removed the command and command alias from the product. The command has been replaced by the more human readable value of TEXTEDIT. If you copy settings from an older version this can cause problems. There are two options to resolve the issue. 
  1. Add DDEDIT as a Command Alias in the acad.PGP file (see instructions above). 
  2. Modify the double click actions in the cui. 
    1. Type CUI at the command line. 
    2. Expand the CUI and Partial Customization Files and check the Double Click Actions for Mtext, Text, and Dimensions and change the Macro to the TextEdit or MTEDIT. TextEdit works on MText.  
XREF Notifications
There are various system variables that may prevent XREF Notifications. 
  • TRAYSETTINGS - Verify Display icons from services is enabled as well as the Display notifications from services. 
  • XREFNOTIFY - Make sure the value is set to 1 (if you want to be alerted to missing XREFs) and 2 if not. 
  • XNOTIFYTIME - Make sure it is a desired value (The default value is nil) by pasting the following line at the command line: 
(getenv "XNOTIFYTIME") 
To change the value paste the following line at the command line: 
(setenv "XNOTIFYTIME" “Desired Time”)

Missing pc3 printer

Sometimes printers get moved or replaced and the plotter set in the pc3 file is not findable. To fix this problem run the Plot command. Select the pc3 file and AutoCAD should ask you which plotter to use. Select the desired plotter and save the results.

LinkWithin

Blog Widget by LinkWithin

Ad