Aller au contenu

API AutoCAD Mechanical 2004


Messages recommandés

bonjour,

 

j'espere que quelqu'un pourra m'aider car j'ai vraiment des petits soucis avec AutoCAD mechanical 2004.

 

Le but du jeux est de créé un ACMPartRef ( une espece de bloc avec attributs liée a la BOMTable de mechanical )

 

Donc sa fonctionne dans la mesure ou j'arrive a le créer et a le placer ou je veux, mais malheureusesement je n'arrive pas a lui fournir les valeurs pour ses attributs.

 

Entre le code exemple, l'ancien code sur la 2000, et le code que j'ai mis en oeuvre dans la 2004, il n'y a strictement aucun rapport.

 

J'ai systematiquement ( a mon idée ) des fonctionnements etrange de l'API mechanical ...

 

j'ai reussit a contourner tous les problemes, le derniers restant est de passer les valeurs des attributs a cet AcmPartRef ...

Pour cela l'API met a disposition ( si g tout suivit au jeux ) une methode setPartData( AcDbObjectId, CMapStringttoString )

 

que j'utilise comme suis :

AutoCAD::ErrorStatus es = acmBomMgr->SetPartData( partRefId, valueMap );

 

qui me retourne a chaque fois eNotOpenForRead !!??!!!

 

j'ai donc ouvert en lecture l'objet pointé par partRefId --> sa me retourne la même chose !!??!!

:casstet:

 

g pas d'idee, je vois pas quel autre objet devrait etre ouvert en lecture ????

 

merci pour vos conseils !

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Quand tu as créé le AcmPartRef, as tu fermé l'objet avant de lui transmettre les données? S'agit-il d'une copie?

 

Voici une routine qui permet de créer un PartRef avec 4 champs (via CMapStringToString valueMap). Tu y trouveras une instruction pPartRef->close() à la fois si il y a création ou s'il y a copie.

 

 

void createPartRef()

{

AutoCAD::ErrorStatus es;

ads_point pt;

 

if (acedGetPoint(0, "Point for AcmPartRef:", pt) != RTNORM)

return;

 

// convert point from UCS to WCS

acdbUcs2Wcs(pt, pt, Adesk::kFalse);

 

AcDbObjectId partRefId;

 

CMapStringToString valueMap;

valueMap.SetAt("NAME", "Name");

valueMap.SetAt("MATERIAL", "Gold");

valueMap.SetAt("NOTE", "MyNote");

valueMap.SetAt("VENDOR", "Me");

 

if(getDataFromUser(valueMap) != Acad::eOk)

return;

 

AcDbObjectId mainBom;

CString mainBomName;

AcDbObjectId targetId = AcDbObjectId::kNull;

 

es = acmBomMgr->getBomTable(mainBom,mainBomName,targetId);

acutPrintf("\ngetBomTable returned : es = %s",acadErrorStatusText(es));

 

Acm::ErrorStatus as;

 

if(mainBom == AcDbObjectId::kNull)

{

// append partRef entity to model space

AcmPartRef* pPartRef = new AcmPartRef();

if (!pPartRef)

return;

 

appendToBlock(pPartRef,partRefId);

 

as = pPartRef->setSymbolDefaults();

pPartRef->setOrigin(asPnt3d(pt));

pPartRef->close();

 

es = acmBomMgr->createBomTable(mainBom,targetId);

if(es != Acad::eOk)

{

acutPrintf("\ncreateBomTable failed : es = %s",acadErrorStatusText(es));

return;

}

es = acmBomMgr->setPartData(partRefId,valueMap);

if(es != Acad::eOk)

{

acutPrintf("\nsetPartData returned : es = %s",acadErrorStatusText(es));

return;

}

}

else

{

AcDbObjectId itemId;

AcDbObjectIdArray refIds;

refIds.append(partRefId);

int nextNo;

bool exists;

 

es = dcgPartRefExists(mainBom,valueMap,exists,itemId);

if(es != Acad::eOk)

{

acutPrintf("\ndcgPartRefExists fails : es = %s",acadErrorStatusText(es));

return;

}

if(exists)

{

AcmCObjArray references;

AcDbIntArray numItemArray;

 

acmBomMgr->getItemReferences(itemId,references,numItemArray);

acutPrintf("\nGot %d references",references.length());

 

// Just get the first reference and copy it

AcDbObjectIdArray* arr = references[0];

AcDbObjectId id = arr->at(0);

AcDbObjectId newId;

AcDbObject* pObj;

 

copyPartRef(id,newId);

 

acdbOpenObject(pObj,newId,AcDb::kForWrite);

 

AcmPartRef* pPartRef = AcmPartRef::cast(pObj);

if(pPartRef)

{

pPartRef->setOrigin(asPnt3d(pt));

}

pObj->close();

 

}

else

{

// append partRef entity to model space

AcmPartRef* pPartRef = new AcmPartRef();

if (!pPartRef)

return;

 

appendToBlock(pPartRef,partRefId);

 

as = pPartRef->setSymbolDefaults();

pPartRef->setOrigin(asPnt3d(pt));

pPartRef->close();

 

acutPrintf("\nPartRef with these data are not ine the BOM table yet");

 

dcgGetNextItemNumber(mainBom,nextNo);

 

char itemNo[255];

sprintf(itemNo,"%d",nextNo);

 

acutPrintf("\nGot %d %s as nextItemNo",nextNo,itemNo);

 

es = acmBomMgr->createItem(itemId,mainBom,refIds,itemNo);

acutPrintf("\ncreateItem returned : es = %s",acadErrorStatusText(es));

es = acmBomMgr->setPartData(partRefId,valueMap);

}

}

}

 

 

Serge

Lien vers le commentaire
Partager sur d’autres sites

merci pour ta reponse rapide :p

 

je vois que le code que tu me proposes n'est pas tres eloigné du code que j'avais testé en premier ...

 

Je vois que tu crées bien la BomTable, c'est bizarre car chez moi cette fonction provoque une assertion , d'ailleurs comme la fonction setOrigin de l'AcmPartRef !!

Pourtant je me suis assuré que lib et include sortait bien du même CD que ma version d'autoCAD 2004 installé ...

 

Malgré que je ne crée pas la bomTable, sa n'empeche en rien AutoCAD de bien gerer la liste de nomenclature.

Pour placer l'AcmPartRef, je suis donc obligé de passer par transformBy( matrix ), le resultat est identique mais faut construre l'AcGeMatrix3d en plus, c'est ballot ... :D

 

Je testerai toutefois ton code ligne pour ligne demain histoire d'etre sur de mes delires, peut etre qu'il serait temps que je me mette en vacance ;)

 

Pour repondre a tes question, je crée l'AcmPartRef comme dans ton exemple avec un new.

Evidement mon reflexe a ete de fermer l'objet dès que je l'avais renseigner correctement, et du coup une reponse du type "eNotOpenForRead " me laissait perplexe puisque je passe un AcDbObjectId. Il etait etonnant de laisser l'objet ouvert en lecture/ecriture pour un appelle a setPartData. dans le doute j'ai donc laisse l'objet ouvert et fermé apres cet appel, mais la même reponse m'a a nouveau ete retournée ??? :exclam:

Quel objet pouvais donc ne pas etre ouvert en lecture !!!

 

Bon enfin je teste et je donne mes resultats !!

Ca commence un peu a m'ennerver Mechanical !!!! :mad2:

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

La version 2002 (AM6) ne permettait que de créer de PartRef ordinaire tandis que maintenant, un PartRef peut être copié et cela nous donne soit une nouvelle instance (pour accompagner une vue) ou soit une copie. La façon de programmer à donc changé. Le Mechanical Browser permet de créer des vues et des assemblages, ce qui nous demande en plus de savoir à quel niveau hiérarchique placer le PartRef.

 

Pour ce qui est du besoin de fermer l'objet, je présume que le programmeur de la fonction setPartData fait l'ouverture et la fermeture de l'objet afin d'être sur du contexte, mais aussi parce que quand on y regarde de près, il existe un méchant dédale de dictionnaires tous inter-reliés et que pour les mettre à jour, il doit effectuer une transaction.

 

Serge

 

Lien vers le commentaire
Partager sur d’autres sites

Bon g teste ton code au point-virgule pret et lui non plus ne fonctionne pas !!

 

detail de ce qui ne vas pas :

 

donc jusque getBomTable returned : es = eNullObjectId le fonctionnement est normal .

ensuite on crée la parRef

AcmPartRef* pPartRef = new AcmPartRef();

 

on l'ajoute a l'espace objet voulut

appendToBlock(pPartRef,partRefId); // retourne bien eOk !!

 

ici sa ne vas plus !!!

as = pPartRef->setSymbolDefaults(); // retourn AcmFail ???????

 

ici sa se passe bien ...

pPartRef->setOrigin(asPnt3d(pt));

pPartRef->close();

 

es = acmBomMgr->createBomTable(mainBom,targetId); // return eNotApplicable et du coup bye bye :mad2:

 

 

bon je pige vraiment pas pourquoi ...

:casstet:

 

 

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

En fait je ne cherche pas à caster l'objet mais a appeler la méthode de la classe parente en espérant contourner l'erreur (setSymbolDefaults est une méthode virtuelle qui existe dans la classe de base).

 

Mais de toute façon, c'est inutile (et peut-être dangeureux). J'ai regardé dans le code de 6 projets différents qui fonctionnent bien et je n'ai pas d'erreur. Il doit y avoir autre chose.

 

Bonne chance.

 

Serge

Lien vers le commentaire
Partager sur d’autres sites

Ahryman40k

 

Hier, je t'avais dit que je n'avais pas testé. J'avoue avoir donné une réponse rapide. Cela venait d'une bout de code où j'avais dérivé une classe à partir de AcmSymbolStd et que cette fonction devenait accessible depuis l'objet même. Sinon, effectivement, cela veut dire appeler une méthode statique.

 

Il doit y avoir autre chose dans ton dessin qui cause l'erreur.

 

Serge

 

Lien vers le commentaire
Partager sur d’autres sites

Franchement je vois pas ce qui pourrait causer l'erreur ...

 

En fait il s'agit toujours de ma fameuse bibli de composant parametriques 2D, suivant la config,

si une personne est dans AutoCAD suite a l'insertion d'une piece, je place un bloc avec attributs contenant des infos de nomenclatures ... On peut ensuite faire des traitements sur ces blocs pour contruire une nomenclature ... la dedans il n'y a aucune erreur ...

Dans le cas d'AcadM, je charge dynamiquement un autre ARX qui expose une interface COM dont je me sert pour lui demander d'inserer un AcmPartRef dans le dessin avec des infos particulieres ...

 

Je n'ai jusque maintenant jamais rencontré de problemes particuliers a faire des ARX de ce type ... Je vais recompiler les exemples AcadM pour voir, mais il me semble que j'ai egalement eut des soucis avec ... Pourtant c'est bien le SDK extrait du même CD que l'Applie ...

 

Je fais recommencer de 0, car j'en perds mon latin !! ( arf non la mode est au Grec ;) )

Lien vers le commentaire
Partager sur d’autres sites

Ahryman40k

 

Initialement, je croyais que ton besoin d'appeler explodeToOwnerSpace était pour faire un équivalent de Burst et d'accoler un PartRef automatiquement, non pour supporter 2 environnements.

 

On est en train de développer eBOM3 dont l'une des caractéristiques est de surveiller l'insertion de symboles Standards de Mechanical ("Iso" ou "Ansi") qui ne seraient pas conformes à l'inventaire du client. Selon le cas, convertir le PartRef automatique de Mechanical en "Profilé d'acier" ou en "Non conforme". Selon le cas toujours, on lit de l'information supplémentaire depuis une table de correspondance d'une base de donnée pour obtenir des numéros d'inventaire, description, etc.

 

Bonne chance, c'est un beau projet.

 

Serge

Lien vers le commentaire
Partager sur d’autres sites

C'est un beau projet qui fonctionne depuis plusieurs mois deja mais malheureusement qui possede une tache sombre dans son fonctionnement avec mechanical ...

 

Je ne suis pas certain de vraiment avoir compris le fonctionnement de la nomenclature et des partRef sous mechanical ( je suis passé un peu vite a l'essentiel ... )

 

Si tu es d'accord, je veux bien un cours de rattrapage, tu as l'air de bien connaitre le sujet :P

Lien vers le commentaire
Partager sur d’autres sites

Trop puissant,

 

Alors g modifie le code de l'exemple car sa peté sur AcmPartRef->setOrigin( AcGePoint3d )

le parametre passé etait obtenue par ceci :

int res = ads_getpoint(NULL,"\nSelect point :",asDblArray(pnt));

 

je ne sais pas ce que fait asDblArray sur un AcGePoint3d, mais surement que le point n'etait plus valide car en passant un point fixe

AcmPartRef->setOrigin( AcGePoint3d( 10,10,0) ), par exemple sa fonctionne ??

 

2e chose bizarre

AutoCAD Mechanical PP 2004 DX plante pour l'exemple avec la modif ci-dessus

Mais mon second AcadM2004 qui est une version pour Michelin lui fonctionne !!??!!!

 

Ca tombe bien, de toute facon c'est sur cette version que sa devra tourner ...

 

DX me laisse perplexe, car je me rappelle avoir egalement eut des problemes avec la version de AutoCAD et MDT2004 ... :question:

 

Bon enfin bref, par contre je n'ai aucun lien entre ces partref et la base de nomenclature ...

 

Ce que je ne comprend pas c'est que j'avais un code en 2000 qui fonctionnait sans probleme, et la y'a pas moyen ... je comprend pas ou sa delire ... :casstet:

Lien vers le commentaire
Partager sur d’autres sites

Si SetOrigin ne comporte pas de modèle avec un point2d, il faut convertir les données, ce qui est assez fréquent comme manoeuvre.

 

Tu peux te créer des fonctions de conversion:

void PtArxToAds (T PointArx, ads_point& PointAds)

{

PointAds[X] = PointArx.x;

PointAds[Y] = PointArx.y;

PointAds[Z] = PointArx.z;

}

ou son inverse

 

J'utilise AutoCAD Mechanical 2004 avec Inventor 7 (donc pas DX). Tu commence à me soulever des doutes.

 

Tant qu'à y être, a tu déjà utiliser les interfaces pour VBA? On peut créer un objet avec le getInterface mais par la suite, tous les membres sont inaccessibles. Je crois qu'ils ont été conçus pour Mechanical Desktop, et non Mechanical tout court.

 

Serge

Lien vers le commentaire
Partager sur d’autres sites

J'ai trouvéééééé !!! Seulement le probleme, maintenant il me faut le resoudre ...

 

Le sample TestPartRef fonctionnant ( apres qlq modifs, mais fonctionnant ), je ne comprenais pas pourquoi mon ARX explosait la ou le sample fonctionnait !!!

 

En fait c'est un ARX que je charge a la volée, mais dont g desactivé le message d'erreur lorsque le chargement s'effectue mal :)

En fait il ne charge pas ! sa explique bcp -_-'

 

Commande: _appload

TrBCMBOM.arx n'est pas compatible avec cette version de AutoCAD.

AcRxDynamicLinker n'a pas chargé 'C:\BUSAPPS\Rbcm\Mv6\Frfr\LibMgr\TrBCMBOM.arx'

C:\Program Files\Autodesk\Acadm 2004\acad.exeImpossible de charger le fichier

TrBCMBOM.arx.

 

le plus drole, c'est qu'il me dit qu'il n'est pas compatible avec cette version d'AutoCAD alors que c'est les même libs que le sample ... j'en ai marre ... :casstet:

Lien vers le commentaire
Partager sur d’autres sites

Je retire ce que j'ai dit,

apperement g eut un tit soucis de compil et sa chargeait plus !

Maintenant il se recharge mais le resultat est toujours le même ...

 

mon code :

 

 
ARXLock lockApp;
ads_point pnt;
// CString numItemColumnName;
Adesk::Int16 numOfItems = 1;

int res = acedGetPoint(NULL,"\nSelect point :",pnt);
if( res == RTCAN || res == RTERROR ) 
return AutoCAD::eOk;

// creates new instance of AcmPartRef and sets defaults
AcmPartRef *pRef = new AcmPartRef;
pRef->setSymbolDefaults(); // will create data id, because we didn't initialize it.
pRef->setOrigin( asPnt3d( pnt ) );

// attempts to add partref to database
AcDbObjectId partId;
if ( appendToBlock(pRef, partId) != Acad::eOk) 
{
delete pRef;
return AutoCAD::eOk;
}
pRef->close();

acmBomMgr->setPartData(partId,numOfItems,valueMap); // et sa pete ici

 

donc la partref est crée mais aucune valeur dedans ...

valueMap doit il avoir des valeurs particulieres ??

Lien vers le commentaire
Partager sur d’autres sites

Est-ce que tu as crée valueMap?

 

CMapStringToString valueMap;

valueMap.SetAt("NAME", "Name");

valueMap.SetAt("MATERIAL", "Gold");

valueMap.SetAt("NOTE", "MyNote");

valueMap.SetAt("VENDOR", "Me");

 

Est-ce que ces champs correspondent au standard actif? Voir Options -> AM:Standards -> BOM Support

 

Serge

Lien vers le commentaire
Partager sur d’autres sites

J'ai finalement trouvé le probleme !!

( Comme quoi une semaine de recul sa fait du bien !! )

 

En fait le premier ARX recoit un evenement COM, charge un second ARX qui possede une interface qui va me permettre d'obtenir des renseignements sur mechanical.

 

Le but etant de ne pas compiler 2 fois le même ARX ( un pour AutoCAD et l'autre pour AcadM ), j'ai deporté toutes les manipulations de acadM dans un ARX a part ( le second ).

c'est dans ce second ARX que je manipule Mechanical via COM.

 

Apparement de la partie evenementielle du premier lorsque je construit la partie COm du second et que je l'interroge, le contexte ne permet pas d'avoir acces a AcadM ??? Alors que j'accede aux objets comme la Db AutoCAD ...

 

Si en fait c'est une commande ARX du premier qui construit et fait les appels sur le second, le même code fonctionne et j'accede sans erreur a mechanical !!

 

2 solutions s'offrent a moi :

Ou je trouve le probleme du contexte d'appel ( resource ou autre ?? Mais les essai ne sont pas concluant )

Ou je fais les même les memes appels depuis une commande ARX, auquel cas comment passer et recuperer des arguments dans une commande ARX ???

 

Je me suis deja lancé dans plusieurs essais, acedGetArgs ne recupere rien apres un sendStringToExecute() ... Aurais je des problemes de syntaxe :

 

ARXAcadTools acadUtl;

CString strCmd;

strCmd.Format("TrTest1\n%f,%f,%f\nDESCR\nMa description", mLastInsertPoint.x, mLastInsertPoint.y, mLastInsertPoint.z);

acadUtl.sendCommand( strCmd );

 

g egalement fais l'essai avec des espaces plutot que \n sans resultats ...

merci pour ton aide Serge.

 

 

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Tant mieux si ça fonctionne.

 

Je m'interroge quand même sur la raison du COM. Au lieu de faire un gros Arx pour AutoCAD seul et un gros pour Arx Mechanical, ce qui donne 2 fichiers, 2 projets, tu fait un petit Arx pour AutoCAD et un petit Arx-Com pour Mechanical, ce qui donne aussi 2 fichiers, 2 projets.

 

De plus, l'implémentation d'objets via une interface est beaucoup laborieuse que du C++ standard, que ce soit pour la conversion de données en safearray, variant, bstr, etc, utiliser des CMapStringToString, l'initialisation et le verrouillage de l'application, etc.

 

Si tu veux diviser ton projet en 2 fichiers, tu peux compiler une premier dll et exporter le fonctions en les réimportant via un fichier .h. Tu peux facilement définir statiquement les fonctions à exporter dans le fichier .def. Si tu veux vraiment utiliser une interface, l'exemple de Smiley pourra t'aider.

 

Tu peux importer et exporter dynamiquement des classes d'un arx à l'autre via les declspec

ex emple dans un .h:

#define MACLASSE __declspec(dllexport)

#pragma message( " Exporting MaClasse_Dll" )

#define MACLASSE __declspec(dllimport)

#pragma message( " Importing MaClasse_Dll" )

 

dans le cpp

HINSTANCE hDLL; // Handle to DLL

LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer

hDLL = AfxLoadLibrary((LPCSTR) path_Dll);

lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "MaClasse_Dll");

 

et ainsi de suite ;-) .

 

Serge

 

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité