Introduction
Purpose : color 3D objects ( Pipe or Part or insulation)
3 different usecases : the automation of the coloring can be done either
as a rule imbeaded into the part that is executed based on attribut/parameter value
as a post processing user action launched manually
as an automatic Business rule launched at the creation of the object instance
let's see deferent exemples for each usecase and needs
USE CASE1 : Color automaticaly reference part in catalog
Need
We want to drive the color of the the Piping Part & Piping Pipe 3D geometry based on a predefined code color set on a parameter inside the part that can be driven by a design table
Each pipe and part will have a predefined color based on the value of Nominal size
Case for Part
For Piping part it is very easy , you just have to create a simple rule to color the PartBody using ".Color(R,G,B)
Rule Code :
PartBody.SetColor(Color)
Case for pipes
For pipe is much more complex because you don't have acces to the 3D volume. The only way is to use the SetColor method that is applied on the Piping_Rigid_Pipe VPMReference object
This method need as inputs RGB color where R,G,B are 3 integers
in our case the PArameter is R,G,B string so we will need to decompose it to use it
Rule code :
let MyProduct (VPMReference) let MyShape (VPMRepReference) let MyShapeInst(VPMRepInstance) let MyPiping(Piping_Rigid_Pipe) // Find Root let roots(List) let rootOfEditor(VPMReference) let lOcc(List) let rootOccurrence,findOcc(ProductOccurrence) roots = GetEditorRoots("VPMReference") if roots->Size() == 1 { rootOfEditor = roots[1] } // Find VPMReference from feature let lRepInsts(List) let lRepRefs(List) MyShape=GetPLMOwner(PartBody) //Message("Shape: ", MyShape.V_Name) lRepInsts = MyShape->ListInstances(rootOfEditor) if (lRepInsts.Size() > 0) { set MyShapeInst = lRepInsts[1] } set MyProduct = MyShapeInst.Owner //Notify("MyProduct : #",MyProduct.Name) set MyPiping = MyProduct //Convert string "R,G,B" to integer list (R,G,B) let RGBColor,CodeColor,separator(String) let RGBList(List) let separatorPosition,NextseparatorPosition,i(Integer) //Split RGB string with "," separator = "," RGBColor =PipeColor i=1 separatorPosition=0 NextseparatorPosition=0 for i while NextseparatorPosition <> RGBColor.Length() { NextseparatorPosition = RGBColor.Search(separator,separatorPosition) if(NextseparatorPosition==-1) NextseparatorPosition = RGBColor.Length() CodeColor=RGBColor->Extract(separatorPosition,NextseparatorPosition-separatorPosition) RGBList.Append(CodeColor) separatorPosition = NextseparatorPosition + 1 } //Notify("ListRGB.Size() = ", RGBList.Size()) // Convert R, G and B strings to Integers let R(Integer) let G(Integer) let B(Integer) let R_St(String) let G_St(String) let B_St(String) R_St=RGBList->GetItem(1) G_St=RGBList->GetItem(2) B_St=RGBList->GetItem(3) //Notify("R = #, G = #, B = #", R_St, G_St, B_St) Set R=R_St.ToReal() Set G=G_St.ToReal() Set B=B_St.ToReal() //Notify("R = #, G = #, B = #", R, G, B) MyPiping.SetColor(R,G,B)
USE CASE2 : Post processing rule/action
Need1 : Color pipe based on lineID Name
Simple case : Color pipe based on lineID Name with the name of lineID is hardcoded inside the rule
Code Example:
let iRefLineID(String) let iPipe(Piping_Rigid_Pipe) iRefLineID=iRef->GetLineIDName() iPipe=iRef.Reference if (iRefLineID == ("PL001")) { iPipe.SetColor(255,255,128) } else if (iRefLineID == ("PL002")) { iPipe.SetColor(255,128,68) } else if (iRefLineID == ("PL003")) { iPipe.SetColor(128,128,192) }
Need2 : Color pipe based on LineId Fluid Name
advanced : Color Pipe based on LineId Fluid Name (from Techno table)
Code Example:
/* Prototype: (Void) : #Void */ /* Requirement: This code relies on an additional column in the fluid table (OutfittingColor) */ /* OutfittingColor column will contain the RGB color code for each fluid */ /* Comment: Mind switching ON action's property 'No dialog box when running an action without argument' */ let MessageCatalogName(String) let MessageContent(String) let RootOccurrence(ProductOccurrence) let RootReference(VPMReference) let RootOccurrenceList(List) let RootReferenceList(List) let CachedFuildTable(VolatileInstance) let FluidTable(Ens_FluidTable) let ColumnDescriptors(List) let ColumnDescriptor(EnsParameterDescriptor) let FluidColumnIndex(Integer) let ColorColumnIndex(Integer) let CellsList(List) let FluidCell(EnsTechnologicalTableCell) let ColorCell(EnsTechnologicalTableCell) let Fluid(String) let Color(String) let NbColumns(Integer) let NbRows(Integer) let DuctsList(List) let PartsList(List) let PipeOccurrence(Piping_Pipe_Occurrence) let PartOccurrence(Piping_Part_Occurrence) let GraphicManager(Visualizable) let LineID(Piping_Line) let Count(Integer) let I(Integer) MessageCatalogName = "CDVEKLMessageCatalog_Piping" Count = 0 set CachedFuildTable = new("VolatileInstance", "", NULL) set FluidTable = AccessResource("PipingSpecificationResource|Fluid", "Ens_FluidTable") if FluidTable <> NULL { I = 1 FluidColumnIndex = 0 ColorColumnIndex = 0 FluidTable->GetColumnDefinitions(ColumnDescriptors) for I while I <= ColumnDescriptors->Size() { set ColumnDescriptor = ColumnDescriptors->GetItem(I) if ColumnDescriptor == NULL continue /* XXX: Fluid table column names and types are hardcoded here... */ if ColumnDescriptor.Type <> "String" continue else if ColumnDescriptor.Name == "Fluid" FluidColumnIndex = I else if ColumnDescriptor.Name == "OutfittingColor" ColorColumnIndex = I } if FluidColumnIndex == 0 or ColorColumnIndex == 0 { MessageContent = BuildMessageNLS(MessageCatalogName,"PIP_0002_ERR_FluidTableMissingColors" , I - 1, Count) if MessageContent->Length() <= 0 Notify("Piping fluid table does not defined any colours for outfitting...") else Notify(MessageContent) exit } I = 1 FluidTable->GetSize(NbRows, NbColumns) for I while I <= NbRows { if FluidTable->GetRow(I, CellsList) == false continue set FluidCell = CellsList->GetItem(FluidColumnIndex) set ColorCell = CellsList->GetItem(ColorColumnIndex) if FluidCell == NULL or ColorCell == NULL continue Fluid = FluidCell->GetAttributeString("ValueAsString") Color = ColorCell->GetAttributeString("ValueAsString") CachedFuildTable->SetAttributeString(Fluid, Color) } } else { MessageContent = BuildMessageNLS(MessageCatalogName,"PIP_0001_ERR_FluidTableNotDefined") if MessageContent->Length() <= 0 Notify("No fluid table defined for Piping...") else Notify(MessageContent) } /* XXX: Improve this by retrieving active level's root parent? */ RootReferenceList = GetEditorRoots("VPMReference") if RootReferenceList->Size() == 1 set RootReference = RootReferenceList->GetItem(1) if RootReference <> NULL set RootOccurrenceList = RootReference->ListOccurrences(RootReference) if RootOccurrenceList <> NULL and RootOccurrenceList->Size() == 1 set RootOccurrence = RootOccurrenceList->GetItem(1) if RootOccurrence <> NULL { I = 1 set DuctsList = RootOccurrence->Query("Piping_Pipe_Occurrence", "") set PartsList = RootOccurrence->Query("Piping_Part_Occurrence", "") for I while I <= DuctsList->Size() + PartsList->Size() { set LineID = NULL set GraphicManager = NULL if I > 0 and I <= DuctsList->Size() { set PipeOccurrence = DuctsList->GetItem(I) if PipeOccurrence == NULL continue set LineID = PipeOccurrence->GetLineIDObject().Reference set GraphicManager = PipeOccurrence } else if I <= DuctsList->Size() + PartsList->Size() { set PartOccurrence = PartsList->GetItem(I - DuctsList->Size()) if PartOccurrence == NULL continue set LineID = PartOccurrence->GetLineIDObject().Reference set GraphicManager = PartOccurrence } if GraphicManager == NULL continue if LineID == NULL GraphicManager.Color = "#FFFFFF" else if CachedFuildTable->HasAttribute(LineID.V_Fluid) == false GraphicManager.Color = "#FFFFFF" else { GraphicManager.Color = CachedFuildTable->GetAttributeString(LineID.V_Fluid) Count = Count + 1 } } MessageContent = BuildMessageNLS(MessageCatalogName,"PIP_0003_INF_ElementsCountNotification" , I - 1, Count) if MessageContent->Length() <= 0 Notify(ToString(I - 1) + " Piping element(s) analysed, " + ToString(Count), " colorised.") else Notify(MessageContent) }
Rules
Need3 : Color insulation based on "insulation Type" attribute
the value of the color of the insulation is retreive from the "Insulation type" Techno table
Code exemple:
/* Prototype: (Void) : #Void */ /* Requirement: This code relies on an additional column in the InsulationType table (OutfittingColor) */ /* OutfittingColor column will contain the RGB color code for each fluid */ /* Comment: Mind switching ON action's property 'No dialog box when running an action without argument' */ let MessageCatalogName(String) let MessageContent(String) let RootOccurrence(ProductOccurrence) let RootReference(VPMReference) let RootOccurrenceList(List) let RootReferenceList(List) let CachedFuildTable(VolatileInstance) let CachedInsulationTypeTable(VolatileInstance) /* Test Insulation */ let FluidTable(Ens_FluidTable) let InsulationTypeTable(Ens_InsulationTypeTable) /* Test Insulation */ let ColumnDescriptors(List) let ColumnDescriptor(EnsParameterDescriptor) let FluidColumnIndex(Integer) let InsulationTypeColumnIndex(Integer) let ColorColumnIndex(Integer) let CellsList(List) let FluidCell(EnsTechnologicalTableCell) let InsulationTypeCell(EnsTechnologicalTableCell) /* Test Insulation */ let ColorCell(EnsTechnologicalTableCell) let Fluid(String) let InsulationType (String) /* Test Insulation */ let Color(String) let NbColumns(Integer) let NbRows(Integer) let DuctsList(List) let PartsList(List) let InsulationList(List) /* Test Insulation */ let PipeOccurrence(Piping_Pipe_Occurrence) let PartOccurrence(Piping_Part_Occurrence) let InsOccurence(Piping_Insulation_Occurrence) /* Test Insulation */ let GraphicManager(Visualizable) let LineID(Piping_Line) let InsRef(Piping_Insulation) /* Test Insulation */ let Count(Integer) let I(Integer) Count = 0 set CachedInsulationTypeTable = new("VolatileInstance", "", NULL) /* Test Insulation */ // retreive InsulationType table from Datasetup set InsulationTypeTable = AccessResource("PipingSpecificationResource|InsulationType", "Ens_InsulationTypeTable") /* Test Insulation */ // Retreive Column index for InsulationType and Color in InsutlationTypeTable if InsulationTypeTable <> NULL { I = 1 InsulationTypeColumnIndex = 0 ColorColumnIndex = 0 InsulationTypeTable ->GetColumnDefinitions(ColumnDescriptors) for I while I <= ColumnDescriptors->Size() { set ColumnDescriptor = ColumnDescriptors->GetItem(I) if ColumnDescriptor == NULL continue /* XXX: Insulation Type table column names and types are hardcoded here... */ if ColumnDescriptor.Type <> "String" continue else if ColumnDescriptor.Name == "InsulationType" InsulationTypeColumnIndex = I else if ColumnDescriptor.Name == "OutfittingColor" ColorColumnIndex = I } // If no InsulationType or OutfittingCollor Collumn in the table , Message if InsulationTypeColumnIndex == 0 or ColorColumnIndex == 0 Notify("Piping Insulation Type table does not defined any colours for outfitting...") else Notify("InsulationType & OutfittingColor columns found") // Build InsulationType value list and Color value list for from the Insulation Table I = 1 InsulationTypeTable->GetSize(NbRows, NbColumns) for I while I <= NbRows { if InsulationTypeTable->GetRow(I, CellsList) == false continue set InsulationTypeCell = CellsList->GetItem(InsulationTypeColumnIndex) set ColorCell = CellsList->GetItem(ColorColumnIndex) if InsulationTypeCell == NULL or ColorCell == NULL continue InsulationType = InsulationTypeCell->GetAttributeString("ValueAsString") Color = ColorCell->GetAttributeString("ValueAsString") CachedInsulationTypeTable->SetAttributeString(InsulationType, Color) } } // If no Insulation Type table table in ResourceSet, Message else { MessageContent = BuildMessageNLS(MessageCatalogName,"PIP_0001_ERR_FluidTableNotDefined") if MessageContent->Length() <= 0 Notify("No Piping Insulation type table defined for Piping...") else Notify("Insulation Type table Name - " + InsulationTypeTable.Name) } // Build the list of Insulations occurent from the ROOT /* XXX: Improve this by retrieving active level's root parent? */ RootReferenceList = GetEditorRoots("VPMReference") if RootReferenceList->Size() == 1 set RootReference = RootReferenceList->GetItem(1) if RootReference <> NULL set RootOccurrenceList = RootReference->ListOccurrences(RootReference) if RootOccurrenceList <> NULL and RootOccurrenceList->Size() == 1 set RootOccurrence = RootOccurrenceList->GetItem(1) if RootOccurrence <> NULL { I = 1 set InsulationList = RootOccurrence->Query("Piping_Insulation_Occurrence", "") for I while I <= InsulationList->Size() { set GraphicManager = NULL if I > 0 and I <= InsulationList->Size() { set InsOccurence = InsulationList->GetItem(I) if InsOccurence == NULL continue set InsRef = InsOccurence.Reference set GraphicManager = InsOccurence } if GraphicManager == NULL continue // check if the table contains the value of Insulation Type set on the Insulation Reference if CachedInsulationTypeTable->HasAttribute(InsRef.V_InsulationType) == false { GraphicManager.Color = "#FFFFFF" Notify("InsulationType not found" + " - " + InsulationTypeTable.Name + " - " + InsulationTypeColumnIndex + "-" + InsulationType + " - " + ColorColumnIndex + "-" + Color + " - " + CachedInsulationTypeTable.Name) } // If yes , retreive corresponding color else { GraphicManager.Color = CachedInsulationTypeTable->GetAttributeString(InsRef.V_InsulationType) Count = Count + 1 Notify("InsulationType - " + InsRef.V_InsulationType ) } } MessageContent = BuildMessageNLS(MessageCatalogName,"PIP_0003_INF_ElementsCountNotification" , I - 1, Count) if MessageContent->Length() <= 0 Notify(ToString(I - 1) + " Piping element(s) analysed, " + ToString(Count), " colorised.") else Notify(MessageContent) }
3DXML
Video
USE CASE3 : Business Rule driven
Need1 : Color pipe when the link with the lineID is created
Coloring tubing, Piping HVAC according Parent LineID information
Remark : an EKL rule to be executed automaticaly in real time. this rule is attached to the Collaborative space through a ResourceSet
The function must be done automatically via Business Rule. Objective is to color object live during the design of the piping network.
To avoid having impact on the overall App performances it could be better to use an Action that user will execute manually instead of using this method
Setup:
Put in place Business Rule (BR) in
- The resource : “Business Logic for Items”
- BR “After creation of PPR Link”
This BR is called during each creation of implement links. This is the case when a piping object is attached to a LineID.
So we can use it to controle the associated line to a pipe and set automatically the good color
Video:
Code:
//Notify("ImplementLink Rule") let lSources(List) let lTargets(List) let ustrRelationName(String) let iRigidPipe(Piping_Rigid_Pipe) let iLineInst(Piping_Line_Inst) set lSources = Parameters->GetAttributeObject("Source") set lTargets = Parameters->GetAttributeObject("Target") ustrRelationName = Parameters->GetAttributeString("RelationType") if ((ustrRelationName == "PLM_ImplementLink_Target") and (lSources.Size() > 0) and (lTargets.Size() > 0)) { let sourcePhysicalInstance(VPMInstance) let targetLogicalInstance(RFLVPMLogicalInstance) set targetLogicalInstance = lTargets[lTargets.Size()] set sourcePhysicalInstance = lSources[lSources.Size()] if (sourcePhysicalInstance <> NULL and targetLogicalInstance <> NULL) { let ustrLogicalInstanceName(String) let ustrPhycialInstanceName(String) ustrLogicalInstanceName= targetLogicalInstance.Name ustrPhycialInstanceName= sourcePhysicalInstance.Name if(sourcePhysicalInstance.IsSupporting("Piping_Valve_Inst")) { sourcePhysicalInstance.Name = targetLogicalInstance.Name } else if(sourcePhysicalInstance.IsSupporting("Piping_Pipe_Inst") AND targetLogicalInstance.IsSupporting("Piping_Line_Inst")) { set iRigidPipe=sourcePhysicalInstance.Reference set iLineInst = targetLogicalInstance Notify("Pipe : #, Line ID : #",sourcePhysicalInstance.Name,targetLogicalInstance.Name) if(iLineInst.Name == "FFL00001") { iRigidPipe.SetColor(51,63,255) } else { iRigidPipe.SetColor(14,129,40) } } else if(sourcePhysicalInstance.IsSupporting("HVAC_Duct_Inst") AND targetLogicalInstance.IsSupporting("HVAC_Line_Inst")) { let fexibleDuct (HVAC_Flexible_Duct) let rigid_Duct1 (HVAC_Rigid_Duct) } else if(sourcePhysicalInstance.IsSupporting("Piping_Insulation_Inst") AND targetLogicalInstance.IsSupporting("Piping_Line_Inst")) { let pipeInsulation (Piping_Insulation) set pipeInsulation = sourcePhysicalInstance.Reference let prd(Piping_Rigid_Pipe) let Opacity(Integer) Opacity = 50 pipeInsulation.SetOpacity(Opacity) if(iLineInst.Name == "FFL00001") { pipeInsulation.SetColor(51,63,255) } else { pipeInsulation.SetColor(14,129,40) } } } }