evereux / pycatia

python module for CATIA V5 automation
MIT License
196 stars 53 forks source link

[need some guide] get all holes in one CAT drawing and put bolt into the holes #186

Closed ZackZouJ closed 8 months ago

ZackZouJ commented 9 months ago

Hello , I'd like to check all holes in one CAT drawing (include several parts) , I can list all the parts under the drawing, but how to get all the holes under these parts and put bolit into it automatically, I have tried but have no idea, could you please give some guidence of how to achieve this goal? thank you in advance

evereux commented 9 months ago

Your question isn't making sense to me. Get holes in CATDrawing and put bolt into holes? Can you provide images showing what you mean please?

Generally, when I'm trying to solve an issue I'll break it down into steps. How would I do it manually? I'd record a macro and see what methods I'd need.

ZackZouJ commented 9 months ago

2024-01-13 21_36_44-Window Hello. sorry for the misunderstanding, I have put one screenshot to clarify it

  1. in the screenshot, i have one part and some bolts
  2. I want to list all the holes in the parts (point 1 in the screenshot) then put the bolts into these holes automatically, assembly these bolts one by one is a waste of time , so i think if the bolts are standard parts, pycatia can help to do these automatically to save my life. I think pycatia can do it instead of VBA, I planned to check some code script in the demo for several hours, but didn;t find the way to do it, what i can do now is only list all the parts in the drawing. hope this can make the question clear , thank you !
evereux commented 9 months ago

So you want to automatically position bolts in an assembly? Nothing to do with a CATDrawing. I come from the aerospace industry and believe me I know your pain.

Do this manually for one and record a macro. Read the macro and find what methods are required. That's got to be your starting point.

I don't know how easy it will be to pick the hole and bolt surfaces programmatically for alignment? I've never tried. I suspect you'll need lines and points for that. Maybe someone else has experience with this. If I have some spare time I'll have a play.

ZackZouJ commented 9 months ago

Hello , Many thanks for the suggestion, I will also follow your thinking way to got the result, hope I can solve it , I will share it if I have solved this problem, thanks again for your kindly support, have a great day!!

Mithro86 commented 9 months ago

This is just a rough idea (you could add more "smartness" to it), but if you use "publications" you could do it like this...

Base part with 4 hole axis and one mating plane as publications (placed in a .CATProduct): image

Bolt with axis and mating plane as publications: image

from pycatia import catia
from pycatia.enumeration.enumeration_types import cat_constraint_type, cat_constraint_orientation

caa = catia()
document = caa.active_document
product = document.product
products = product.products
constraints = product.constraints()

# Array for file
array = [0] * 1
array[0] = "C:\\Users\\Mithro86\\TEST\\bolt3.CATPart"

# Set base part
base_part = products.item(1)

# Get first four publications
axis = []
for i in range(1,5):
    hole_axis = base_part.publications.item(i)
    hole_axis_ref = hole_axis.valuation
    axis.append(hole_axis_ref)

# Get last publication
base_mating_plane = base_part.publications.item(5)
base_mating_plane_ref = base_mating_plane.valuation

# Add existing component and get publications
bolt_axs = []
bolt_matings = []

for i in range(1,5):
    products.add_components_from_files(array, "All")
    bolt = products.item(products.count)
    bolt_axis = bolt.publications.item(1)
    bolt_axis_ref = bolt_axis.valuation
    bolt_axs.append(bolt_axis_ref)
    bolt_mating = bolt.publications.item(2)
    bolt_mating_ref = bolt_mating.valuation
    bolt_matings.append(bolt_mating_ref)

for i in range(4):
    constraint_axis = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_axs[i], axis[i])
    constraint_plane = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_matings[i], base_mating_plane_ref)
    constraint_plane.orientation = cat_constraint_orientation.index("catCstOrientOpposite")

product.update()
ZackZouJ commented 9 months ago

This is just a rough idea (you could add more "smartness" to it), but if you use "publications" you could do it like this...

Base part with 4 hole axis and one mating plane as publications (placed in a .CATProduct): image

Bolt with axis and mating plane as publications: image

from pycatia import catia
from pycatia.enumeration.enumeration_types import cat_constraint_type, cat_constraint_orientation

caa = catia()
document = caa.active_document
product = document.product
products = product.products
constraints = product.constraints()

# Array for file
array = [0] * 1
array[0] = "C:\\Users\\Mithro86\\TEST\\bolt3.CATPart"

# Set base part
base_part = products.item(1)

# Get first four publications
axis = []
for i in range(1,5):
  hole_axis = base_part.publications.item(i)
  hole_axis_ref = hole_axis.valuation
  axis.append(hole_axis_ref)

# Get last publication
base_mating_plane = base_part.publications.item(5)
base_mating_plane_ref = base_mating_plane.valuation

# Add existing component and get publications
bolt_axs = []
bolt_matings = []

for i in range(1,5):
  products.add_components_from_files(array, "All")
  bolt = products.item(products.count)
  bolt_axis = bolt.publications.item(1)
  bolt_axis_ref = bolt_axis.valuation
  bolt_axs.append(bolt_axis_ref)
  bolt_mating = bolt.publications.item(2)
  bolt_mating_ref = bolt_mating.valuation
  bolt_matings.append(bolt_mating_ref)

for i in range(4):
  constraint_axis = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_axs[i], axis[i])
  constraint_plane = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_matings[i], base_mating_plane_ref)
  constraint_plane.orientation = cat_constraint_orientation.index("catCstOrientOpposite")

product.update()

really a good example, it is amazing you can finish this with so less code.. i think it should with massive code to finish this task. thanks a lot , by the way,I saw you have used some method , like publications, constraints etc in the code, I'm new in CATIA development(some experience with python dev before) , are they from the API tree in https://pycatia.readthedocs.io/en/latest/ ?

Mithro86 commented 9 months ago

About publications in CATIA V5:

https://edstechnologies.com/blog/making-assemblies-easier-with-publications-in-catia-v5/

In my example I created elements on part-level, which I then published.

Doing so makes the elements available in a .CATProduct.

The code then takes the elements found under "publications".

ZackZouJ commented 9 months ago
publications.item(i)
  hole_axis_ref = hole_axis.valuation

many thanks, I have read your post carefully, now I understand that the axis of both slot and bolts should exist in publications first, in my drawing, the hole doesn;t has this kind of publication, I will do it manually and record the marco to see if it is possible to add axis in the publication of holes automatically.

ZackZouJ commented 8 months ago

About publications in CATIA V5:

https://edstechnologies.com/blog/making-assemblies-easier-with-publications-in-catia-v5/

In my example I created elements on part-level, which I then published.

Doing so makes the elements available in a .CATProduct.

The code then takes the elements found under "publications".

I'm trying to do some modification of the code, but faced one problem, in the sample "base_part = products.item(1)" with get the first item in the part and return the object , in normal situation, there will be many parts under the product, i'm trying to get the part object based on user's selection, I have read the "selection" method, but seems document.selection can only return the name of the selection instead of the object. i have list the structure below, if i select axis1 , how can I get the object of part A , like the same result as products.item(1) ? thank you level1----product level2 ----part A level3----publication level4-- axis1 level2----part B

ZackZouJ commented 8 months ago

I have got the answer after several times try, with following code for item in products: if document.selection.item2(1).value.name in item.name: base_part = item

ZackZouJ commented 8 months ago

About publications in CATIA V5:

https://edstechnologies.com/blog/making-assemblies-easier-with-publications-in-catia-v5/

In my example I created elements on part-level, which I then published.

Doing so makes the elements available in a .CATProduct.

The code then takes the elements found under "publications".

Hello, could you please give some suggestion how to add the hole axis in all the slotted hole of one part? in my work environment, these parts doesn;t has the axis and publication, i have tried to read the API tree of pycatia , but didn't got the answer. i tried to record the Marco, I have add the axis from "wireframe " tool, but from the Marco, "Set reference1" is selected by me manually, how can Pycatia got all the holes of one part and add hole axis automatically? thank you

Language="VBSCRIPT"

Sub CATMain()

Set documents1 = CATIA.Documents

Set partDocument1 = documents1.Item("Ctest.CATPart")

Set part1 = partDocument1.Part

Set hybridShapeFactory1 = part1.HybridShapeFactory

Set bodies1 = part1.Bodies

Set body1 = bodies1.Item("PartBody")

Set shapes1 = body1.Shapes

Set assemble1 = shapes1.Item("Bohrbearbeitung")

Set reference1 = part1.CreateReferenceFromBRepName("RSur:(Face:(Brp:(RectPattern.7_ResultOUT;0-1:(Brp:(Hole.7;0:(Brp:(Skt2DWire.7;1)))));None:();Cf12:());WithPermanentBody;WithoutBuildError;WithSelectingFeatureSupport;MFBRepVersion_CXR29)", assemble1)

Set hybridShapeAxisLine1 = hybridShapeFactory1.AddNewAxisLine(reference1)

hybridShapeAxisLine1.AxisLineType = 1

Set hybridBodies1 = part1.HybridBodies

Set hybridBody1 = hybridBodies1.Item("22")

hybridBody1.AppendHybridShape hybridShapeAxisLine1

part1.InWorkObject = hybridShapeAxisLine1

part1.Update

End Sub

evereux commented 8 months ago

Hello, could you please give some suggestion how to add the hole axis in all the slotted hole of one part? in my work environment, these parts doesn;t has the axis and publication, i have tried to read the API tree of pycatia , but didn't got the answer.

For a slotted hole I think you're going to have to generate the axis line yourself if it doesn't exist somewhere in the part (where you'll know it'll be to select it). Easier said than done if you also don't know which surface the axis line should be normal too or which point is at the centre (the point can probably be found if one was used for sketch positioning?). I'm talking here from a completely automated point of view.

This is why I mentioned that I suspect you'll need the points and vector in your part already. The only way I can see this all working reliably is if all the designers work to the same methodology and these points and vectors are in a named geometrical set.

ZackZouJ commented 8 months ago

Hello, could you please give some suggestion how to add the hole axis in all the slotted hole of one part? in my work environment, these parts doesn;t has the axis and publication, i have tried to read the API tree of pycatia , but didn't got the answer.

For a slotted hole I think you're going to have to generate the axis line yourself if it doesn't exist somewhere in the part (where you'll know it'll be to select it). Easier said than done if you also don't know which surface the axis line should be normal too or which point is at the centre (the point can probably be found if one was used for sketch positioning?). I'm talking here from a completely automated point of view.

This is why I mentioned that I suspect you'll need the points and vector in your part already. The only way I can see this all working reliably is if all the designers work to the same methodology and these points and vectors are in a named geometrical set.

yes, I'm quite agree with you standardized design work and good habit can make this work easier, the development shouldn't be the only way to solve the issue, I will talk with my colleague, i will also post the code here if i can go further more. thanks again ๏ผš๏ผ‰

evereux commented 8 months ago

You're welcome. Good luck with this project!

ZackZouJ commented 8 months ago

Hello, could you please give some suggestion how to add the hole axis in all the slotted hole of one part? in my work environment, these parts doesn;t has the axis and publication, i have tried to read the API tree of pycatia , but didn't got the answer.

For a slotted hole I think you're going to have to generate the axis line yourself if it doesn't exist somewhere in the part (where you'll know it'll be to select it). Easier said than done if you also don't know which surface the axis line should be normal too or which point is at the centre (the point can probably be found if one was used for sketch positioning?). I'm talking here from a completely automated point of view.

This is why I mentioned that I suspect you'll need the points and vector in your part already. The only way I can see this all working reliably is if all the designers work to the same methodology and these points and vectors are in a named geometrical set.

tt I met one strange thing during my test today, attached is my test data( production structure, code and result) from the result, you can see "(part1.is_catpart()" returns true , it means the item I got is the CATpart, but when I use method related to the part hsf = part1.hybrid_shape_factory I got the error and tell me the item is the product. why the method got different result ? I got confused

evereux commented 8 months ago

This is a quirk of the COM interface. You've got the Product instance not the Part.


from pycatia import catia
from pycatia.mec_mod_interfaces.part import Part
from pycatia.mec_mod_interfaces.part_document import PartDocument
from pycatia.product_structure_interfaces.product import Product
from pycatia.product_structure_interfaces.product_document import ProductDocument

caa = catia()
application = caa.application
documents = application.documents
product_document: ProductDocument = application.active_document
product: Product = product_document.product
products = product.products
first_item = products.item(1)
print(first_item)  # outputs Product(name="my_part") this is a CATPart in my tree
part_document: PartDocument = PartDocument(first_item.reference_product.parent.com_object)
part: Part = part_document.part
print(part) # outputs Part(name="my_part")
ZackZouJ commented 8 months ago

This is a quirk of the COM interface. You've got the Product instance not the Part.

from pycatia import catia
from pycatia.mec_mod_interfaces.part import Part
from pycatia.mec_mod_interfaces.part_document import PartDocument
from pycatia.product_structure_interfaces.product import Product
from pycatia.product_structure_interfaces.product_document import ProductDocument

caa = catia()
application = caa.application
documents = application.documents
product_document: ProductDocument = application.active_document
product: Product = product_document.product
products = product.products
first_item = products.item(1)
print(first_item)  # outputs Product(name="my_part") this is a CATPart in my tree
part_document: PartDocument = PartDocument(first_item.reference_product.parent.com_object)
part: Part = part_document.part
print(part) # outputs Part(name="my_part")

amazing, I didn't realize Pycatia can be used as this before!! seems a new window has opened , it is really powerful

ZackZouJ commented 8 months ago

Hello @evereux @Mithro86 I met one problem during trying to publication the Axis in geometricalSet the structure of drawing is TEST_CONSOLE/!22/Axis.5 ------------22 (geometricalSet) --------Axis.1 (Axis line of the slotted hole) I have recorded the Macro as below and it create the publication successfully

Sub CATMain()

Set documents1 = CATIA.Documents

Set partDocument1 = documents1.Item("TEST_CONSOLE.CATPart")

Set product1 = partDocument1.GetItem("TEST_CONSOLE")

Set reference1 = product1.CreateReferenceFromName("TEST_CONSOLE/!22/Axis.5")

Set publications1 = product1.Publications

Set publication1 = publications1.Add("Axis1")

publications1.SetDirect "Axis1", reference1

End Sub

then I tried to make the constrain as the code used before , and it works well, the part can be put into the hole successfully

from pycatia import catia
from pycatia.enumeration.enumeration_types import cat_constraint_type, cat_constraint_orientation

caa = catia()
document = caa.active_document
product = document.product
products = product.products
constraints = product.constraints()

array = [0] * 1
array[0] = "C:\\Users\\admin\\TEST\\bolt3.CATPart"

base_part = products.item(1)

axis = []
for i in range(1,5):
    hole_axis = base_part.publications.item(i)
    hole_axis_ref = hole_axis.valuation
    axis.append(hole_axis_ref)

base_mating_plane = base_part.publications.item(5)
base_mating_plane_ref = base_mating_plane.valuation

bolt_axs = []
bolt_matings = []

for i in range(1,5):
    products.add_components_from_files(array, "All")
    bolt = products.item(products.count)
    bolt_axis = bolt.publications.item(1)
    bolt_axis_ref = bolt_axis.valuation
    bolt_axs.append(bolt_axis_ref)
    bolt_mating = bolt.publications.item(2)
    bolt_mating_ref = bolt_mating.valuation
    bolt_matings.append(bolt_mating_ref)

for i in range(4):
    constraint_axis = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_axs[i], axis[i])
    constraint_plane = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_matings[i], base_mating_plane_ref)
    constraint_plane.orientation = cat_constraint_orientation.index("catCstOrientOpposite")

product.update()

later I have do the same in python and create the publication with no error

 caa = catia()
    application = caa.application
    settingControllers1 = caa.setting_controllers()
    documents = application.documents
    product_document: ProductDocument = application.active_document
    product: Product = product_document.product
    products = product.products
    constraints = product.constraints()
    first_item = products.get_item_by_name("TEST_CONSOLE")
    part_document: PartDocument = PartDocument(first_item.reference_product.parent.com_object)
    part: Part = part_document.part
    hsf = part.hybrid_shape_factory
    hy_hybridbody=part.hybrid_bodies
    hb = hy_hybridbody.item("22")
    base_part = products.item(1)
    print(base_part)
    # ==============================Create publication===========================
    reference1 = products.item(1).create_reference_from_name(part.name+"/!"+hb.name+"/"+hb.hybrid_shapes.item(1).name)
    print(reference1)
    publications1 = products.item("TEST_CONSOLE").publications
    i = str(1)
    publications1.add("Axis.5")
    base_part.update()
    publications1.set_direct("Axis.5", reference1)
    visualizationSettingAtt1 = settingControllers1.item("CATVizVisualizationSettingCtrl")
    visualizationSettingAtt1.save_repository()

but when I do the same code to make the constrain, the publication that I create by pycatia, I got the following errors,

File "C:\Users\Administrator\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
  File "C:\Users\Administrator\Desktop\CAT\pythonProject2\main.py", line 664, in Assem_bolt2
    constraint_axis = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_axs[i], axis[i])
  File "C:\Users\Administrator\Desktop\CAT\pythonProject2\.venv\lib\site-packages\pycatia\mec_mod_interfaces\constraints.py", line 134, in add_bi_elt_cst
    return Constraint(self.constraints.AddBiEltCst(i_cst_type, i_first_elem.com_object, i_second_elem.com_object))
  File "<COMObject Connections>", line 2, in AddBiEltCst
pywintypes.com_error: (-2147352567, 'errorใ€‚', (0, 'CATIAConstraints', 'The method AddBiEltCst failed', None, 0, -2147467259), None)

I have checked in CATIA drawing, and didn't find any difference in the drawing about the two pubucations that created by VBA and pycatia. could you please point out the difference between the publication created by VBA and Pycatia? thank you !

evereux commented 8 months ago

I've edited your post so the code is properly formatted.

The error is flagging add_bi_elt_cst. Are bolt_axis[i] and axis[i] Reference objects? Doesn't look like it.

ZackZouJ commented 8 months ago

axis[i]

yes, the error is from this line "constraint_axis = constraints.add_bi_elt_cst(cat_constraint_type.index("catCstTypeOn"), bolt_axs[i], axis[i])" if in axis[i] the publication is created by the python code I have listed above, the axis publication that I created by VBA doesn't has this issue . comment: I have tried several times during these days and today I have found accidentally that if I save the document and close it after make the publication by python , then opened the drawing again, the constain function will work welly ..... if I saved the drawing and put it in the post, you can't reproduce this issue. if i used the code product_document.save() caa.active_window.close() documents.open("C:\Users\Zack\Desktop\test33.CATProduct")

then I will also got the error, I must close the document manually then reopen to make it work.. i don't know why and still checking.

evereux commented 8 months ago

I'm so confused. ๐Ÿ˜„

Can you at least use the correct naming conventions for CATPart,CATProduct and CATDrawing. You keep saying drawing, it isn't a drawing.

If you continue to have an error please open a new ticket. Provide a standalone script that is designed to trigger only the error (not excerpts from your codebase) and provide clear instructions on what's required for someone to run it.

ZackZouJ commented 8 months ago

I'm so confused. ๐Ÿ˜„

Can you at least use the correct naming conventions for CATPart,CATProduct and CATDrawing. You keep saying drawing, it isn't a drawing.

If you continue to have an error please open a new ticket. Provide a standalone script that is designed to trigger only the error (not excerpts from your codebase) and provide clear instructions on what's required for someone to run it.

๐Ÿ˜ƒ sorry for the confusion, I'm a beginner of this the CATIA dev, I will follow your suggestion to make the description more formal , haha~~ let me have a check, I will post the CATDrawing and the code in a new ticket if didn't solved, thanks again and have a great day!

evereux commented 8 months ago

You've now said CATDrawing, as far as I can see a CATDrawing isn't applicable here.

Also, please don't upload CATIA data here. There's always a chance of a version incompatibility. Just describe the data you're working with or provide screenshots so I can reproduce.