Pipe Family ID Returning Null After Creating a Pipe in Civil 3D

Pipe Family ID Returning Null After Creating a Pipe in Civil 3D

tarekahmed136
Contributor Contributor
1,377 Views
6 Replies
Message 1 of 7

Pipe Family ID Returning Null After Creating a Pipe in Civil 3D

tarekahmed136
Contributor
Contributor

I am working on a custom tool in Civil 3D, and I'm encountering an issue when creating a pipe programmatically. After the pipe is created, I am trying to access the Pipe Family ID (using pipe.PartFamilyId), but it returns ObjectId.Null rather than a valid ID.

 

I even Used the Snoop command in the DWG file to check the pipe's properties, and the Pipe Family ID is still ObjectId.Null.

 

You will find the code i used below.

 

 I checked parameters.PartFamily to make sure I got the correct ID, and it's correct. However, the Pipe Family ID is still returning ObjectId.Null after creating the pipe.

 

public class PipesService
    {
        public static ObjectId AddLinePipe(Document document, ObjectId networkId, Point3d startPoint, Point3d endPoint, PipeCreationParameters parameters)
        {
            var pipeId = ObjectId.Null;

            var lineSegment3D = new LineSegment3d(startPoint, endPoint);

            using (Transaction transaction = document.TransactionManager.StartTransaction())
            {
                var network = networkId.GetObject(OpenMode.ForWrite) as Network;

                network.AddLinePipe(parameters.PartFamily, parameters.PartSize, lineSegment3D, ref pipeId, true);

                transaction.Commit();
            }

            return pipeId;
        }

        public static ObjectId AddCurvePipe(Document document, ObjectId networkId, CircularArc3d circularArc3D, PipeCreationParameters parameters)
        {
            var endDirection3D = circularArc3D.GetTangent(circularArc3D.EndPoint).Direction;

            var endDirection = new Vector2d(endDirection3D.X, endDirection3D.Y).Negate();

            PipeCurveGeometry pipeCurveGeometry = new PipeCurveGeometry(circularArc3D.StartPoint, circularArc3D.EndPoint, endDirection);

            var pipeId = ObjectId.Null;
            using (Transaction transaction = document.TransactionManager.StartTransaction())
            {
                var network = networkId.GetObject(OpenMode.ForWrite) as Network;

                pipeId = network.AddCurvePipe(parameters.PartFamily, parameters.PartSize, pipeCurveGeometry, true);

                transaction.Commit();
            }

            return pipeId;
        }
    }

 

 

tarekahmed136_0-1739886764459.png

 

0 Likes
Accepted solutions (1)
1,378 Views
6 Replies
Replies (6)
Message 2 of 7

Norman_Yuan
Mentor
Mentor

The code you post is probably irrelevant, because it only calls Network.AddLine[Curve]Pipe(). The real cause lies in the PipeCreationParameters object, which must be a custom class object created by your code. That is, the PartFamily/Size information in that object must be valid: is the Family available in the Network's PartsList?

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 7

tarekahmed136
Contributor
Contributor

The PipeCreationParameters object is initialized with both the PartFamilyId and PartTypeId. Here’s how I set it up:

  1. I retrieved the first available PartList in the drawing.
  2. From that PartList, I obtained all the families and selected the first one.
  3. From that family, I retrieved all available sizes and selected the first one.
  4. I then initialized the PipeCreationParameters object by passing the selected PartFamilyId and PartSizeId to ensure they are correctly assigned.

Before calling Network.AddLine[Curve]Pipe(), I explicitly checked the PartFamilyId inside the PipeCreationParameters object, and it is correct and available in the network’s PartList. Additionally, the selected size is valid and exists within the family's available sizes.

However, after creating the pipe, the Snoop command shows that the size is assigned correctly, but the family is not, which is confusing. Any idea why this might be happening?

 

 

 

public class PartsListService
    {
        public static List<ObjectId> GetPartsLists(CivilDocument civilDocument)
        {
            return civilDocument.Styles.PartsListSet.Cast<ObjectId>().ToList();
        }
    }

public class PartFamiliesService
    {
        public static List<ObjectId> GetPartFamilies(Document document, ObjectId partsListId, DomainType domainType)
        {
            List<ObjectId> partFamilies;
            using (Transaction transaction = document.TransactionManager.StartTransaction())
            {
                PartsList partsList = partsListId.GetObject(OpenMode.ForRead) as PartsList;

                partFamilies = partsList.GetPartFamilyIdsByDomain(domainType).Cast<ObjectId>().ToList();

                transaction.Commit();
            }

            return partFamilies;
        }

        public static List<ObjectId> GetPartFamilySizes(Document document, ObjectId partFamilyId)
        {
            List<ObjectId> partSizesIds = new List<ObjectId>();

            using (Transaction transaction = document.TransactionManager.StartTransaction())
            {
                PartFamily partFamily = partFamilyId.GetObject(OpenMode.ForRead) as PartFamily;

                for (int i = 0; i < partFamily.PartSizeCount; i++)
                    partSizesIds.Add(partFamily[i]);

                transaction.Commit();
            }

            return partSizesIds;
        }
    }

 

 

 

Then at the command i used that 

 

 

ObjectId partList = PartsListService.GetPartsLists(civilDocument).First();

                ObjectId pipeFamiliy = PartFamiliesService.GetPartFamilies(document, partList, DomainType.Pipe).First();

                ObjectId pipeSize = PartFamiliesService.GetPartFamilySizes(document, pipeFamiliy).First();


                PipeCreationParameters pipeCreationParameters = new PipeCreationParameters(pipeFamiliy, pipeSize);

 

 

0 Likes
Message 4 of 7

Norman_Yuan
Mentor
Mentor

OK, the logic of getting the PartsList (and Families in it) is fraud:

You do not randomly decide which PartsList is to use (not to mention of casually choosing to use the first one). You choose the PartsList that is ASSIGNED to the network you are adding pipes/structures to. That is, you first open the network, find out the PartsList it uses (PartsListId[Name] property); then you open this designated PartsList for collecting available PartFamilies (and possibly, available PartSizes in each Family). Then you create your PipeCreationParameters object based on these part data.

 

Edit:

Obviously, your logic would work, if the drawing only has 0ne PartsList that applies to only one network or multiple networks all use this PartsList.

 

Since you mention the PartSize is OK, only Family's Id is ObjectId.Null, this is another issue: the PartFamily was added to the PartsList of the drawing from a different network parts catalog from the current catalog.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 5 of 7

tarekahmed136
Contributor
Contributor

I understand your point, but in my case, I am creating a new network, not adding pipes to an existing one. Since this is a new network, there is no pre-assigned PartsList. That’s why I am selecting the first available PartsList in the drawing when creating the network.

The workflow I followed is:

  1. Select the first available PartsList in the drawing (it could be the second or any partlist).
  2. Use that PartsList to create a new network.
  3. Retrieve families and sizes from that same PartsList.
  4. Use a valid PartFamilyId and PartSizeId from that list to initialize the PipeCreationParameters.
  5. Add pipes and structures to the newly created network.

The casual selection of the PartsList, PartFamily, and PartSize is just for testing purposes, but in my case, it should still work since all the values being used are valid and available in the network’s assigned PartsList.

0 Likes
Message 6 of 7

Norman_Yuan
Mentor
Mentor
Accepted solution

Did you assign a PartsList ("the first available PartsList in the drawing") to the newly created network BEFORE adding parts (pipes/structures), that is setting Network.PartsListId[Name] property? This should be between step 2 and 3 (or at least before step 5), but you did not mention it.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 7 of 7

tarekahmed136
Contributor
Contributor

Turns out the issue was exactly what you pointed out. I forgot to assign the Network.PartsListId. I assumed it would be assigned automatically once I added a part using a family from the PartsList to the network. Thanks a lot for your help

0 Likes