ऑटोलिस्प कुछ उपयोगकर्ताओं के लिए ब्लॉक विशेषता को सही ढंग से सेट नहीं कर रहा है
पहली बार पूछने वाला, इसलिए उम्मीद है कि मैं समस्या का अच्छी तरह से वर्णन कर रहा हूं।
हमारी कंपनी में हमारा ऑटोलिसप कोड है जो कई व्यक्तियों द्वारा ऑटोकैड के एक ही संस्करण के साथ उपयोग किया जाता है, लेकिन कुछ उपयोगकर्ताओं के लिए लिस्प ने सही ढंग से काम करना बंद कर दिया है।
लिस्प का कार्य निम्नानुसार है:
- उपयोगकर्ता लिस्प चलाता है
- कार्यक्रम निम्नलिखित चीजों के लिए पूछता है:
- ब्लॉक का पैमाना
- ब्लॉक में पाठ के लिए उपसर्ग
- पहली ब्लॉक इकाई के लिए चल रही संख्या
- रनिंग नंबर की वृद्धि
- पहला ब्लॉक कहां रखा जाए
यह एक मार्कर के साथ एक ब्लॉक और निम्न प्रारूप (उपसर्ग) के साथ एक पाठ के लिए नेतृत्व करना चाहिए (संभव मध्य खंड यदि संख्या तीन संख्याओं से युक्त नहीं है) (चल रही संख्या), जैसे PT001 या PX100।
हालांकि ऐसा करने के बजाय कुछ उपयोगकर्ता उपसर्ग और संख्या की कमी का अनुभव कर रहे हैं और केवल पाठ के पूर्वोक्त संभव मध्य भाग को देखना शुरू कर रहे हैं, जबकि अन्य बार एक ही उपयोगकर्ता अनुभव कर सकता है कि केवल उपसर्ग दिखाया गया है। मार्कर को वैसे ही प्रदर्शित किया जाना चाहिए जैसा कि होना चाहिए, लेकिन पाठ केवल अपेक्षा के अनुरूप काम नहीं करेगा।
खामियों के लिए नीचे दिए गए कोड का विश्लेषण करने में किसी भी मदद की बहुत सराहना की जाती है।
यदि कोड "निर्दोष" लगता है, तो मुझे लगता है कि ब्लॉक या इसकी विशेषताओं के साथ कोई समस्या है।
-इ
(defun c:pointnumber()
(setvar "ATTDIA" 0)
(setq sc (getreal "\nEnter scale: "))
(setq px (getstring "\nSet prefix for point number: "))
(setq nr (getint "\nThe number for the first point: "))
(setq ic (getint "\nIncrement of the number: "))
(setq point 1)
(while (/= point nil)
(setq point (getpoint "\nChoose a point: "))
(if (/= point nil)
(progn
(setq inr (itoa nr))
(if (< nr 100) (setq md "0"))
(if (< nr 10) (setq md "00"))
(if (> nr 99) (setq md ""))
(setq ph (strcat px md inr))
(command "insert" "pointnumber" point sc sc 0 ph)
(setq nr (+ nr ic))
)
)
)
(setvar "ATTDIA" 1)(princ)
)
जवाब
आपके वर्तमान कोड के साथ कई समस्याएं हैं: जिनमें से कुछ को केवल बुरा अभ्यास माना जा सकता है, कुछ प्रोग्राम विफल हो जाएंगे यदि उपयोगकर्ता अमान्य डेटा के साथ प्रतिक्रिया करता है, और अन्य कारण के आधार पर कार्यक्रम विफल हो जाएगा या अप्रत्याशित रूप से व्यवहार करेगा। ऑटोकैड वातावरण की सेटिंग्स जिसमें कार्यक्रम निष्पादित किया जाता है।
1. ATTREQ
आपके द्वारा वर्णित व्यवहार के लिए मुख्य अपराधी ATTREQसिस्टम चर है, जो यह निर्धारित करता है कि उपयोगकर्ता INSERTकमांड के भाग के रूप में विशेषता मानों के लिए संकेत प्राप्त करेगा या नहीं । यदि ATTREQ=0
प्रोग्राम चलाया जाता है, तो ब्लॉक को उसके डिफ़ॉल्ट विशेषता मानों के साथ डाला जाएगा।
आप इस सिस्टम चर के वर्तमान मान को संग्रहीत करके और कमांड 1
को कॉल करने से पहले इसे सेट करने के लिए वातावरण के बीच निरंतर व्यवहार सुनिश्चित कर सकते हैं INSERT(यह सुनिश्चित करने के लिए कि विशेषता संकेत जारी किए जाते हैं), और फिर कमांड के बाद या अंत में मूल मूल्य को बहाल करना। कार्यक्रम।
उदाहरण के लिए:
(defun c:test ( / atr )
(setq atr (getvar 'attreq))
(setvar 'attreq 1)
;; ... Do your thing
(setvar 'attreq atr)
(princ)
)
2. OSMODE
जब AutoLISP के माध्यम से एक कमांड पर बिंदु डेटा की आपूर्ति करते हैं, तो बिंदु उस समय किसी भी ऑब्जेक्ट स्नैप मोड से प्रभावित होगा जो बिंदु पर आपूर्ति करता है। मैं यहाँ अपने उत्तर में इसका और अधिक विस्तार से वर्णन करता हूँ ।
इससे बचने का सबसे आसान तरीका है कि ऑटोकेडी को बाद के बिंदु इनपुट के लिए सभी ऑब्जेक्ट स्नैप मोड को अनदेखा करने का निर्देश देने के लिए "_non"
या "_none"
ऑब्जेक्ट स्नैप संशोधक के उपयोग के माध्यम से , जैसे:
(command "insert" "pointnumber" "_non" point sc sc 0 ph)
3. उपयोगकर्ता इनपुट
कार्यक्रम निष्पादन के दौरान त्रुटियों से बचने के लिए आपको उपयोगकर्ता इनपुट या अमान्य उपयोगकर्ता इनपुट की कमी का ध्यान रखना चाहिए - यह if
कथन या initget
फ़ंक्शन के उपयोग के माध्यम से आसानी से प्राप्त किया जाता है, जैसे:
(initget 7) ;; Prevents Enter, zero, or negative numbers
(setq sc (getreal "\nEnter scale: "))
या:
(initget 6)
(if
(and
(setq sc (getreal "\nEnter scale: "))
(setq px (getstring "\nSet prefix for point number: "))
(setq nr (getint "\nThe number for the first point: "))
(setq ic (getint "\nIncrement of the number: "))
)
;; ... Do your thing
)
वैकल्पिक रूप से, आप इनमें से प्रत्येक संकेत के लिए डिफ़ॉल्ट मान कॉन्फ़िगर कर सकते हैं , उदाहरण के लिए, प्रॉम्प्ट पर मेरे ट्यूटोरियल में वर्णित तरीकों में से एक का उपयोग करते हुए :
(setq sc (cond ((getreal "\nSpecify scale <1.0>: ")) (1.0)))
4. स्थानीय बनाम वैश्विक चर
वर्तमान में, आपके कार्यक्रम के सभी चर वैश्विक चर हैं: अर्थात्, वे दस्तावेज़ (ड्राइंग) नामस्थान के भीतर परिभाषित किए गए हैं और कार्यक्रम को पूरा करने के बाद भी अपने मूल्यों को बनाए रखेंगे।
जैसा कि मैंने स्थानीयकरण चर पर अपने ट्यूटोरियल में वर्णन किया है , यह संभावित रूप से समस्याओं का कारण बन सकता है यदि ऐसे चर अनजाने में अन्य कार्यक्रमों द्वारा उपयोग किए जाने वाले वैश्विक चर के साथ अपने नाम साझा करते हैं, या जब कोई प्रोग्राम लूप के भीतर एक सूची या अन्य आकस्मिक डेटा संरचना का निर्माण कर रहा होता है।
जब तक कार्यक्रम के सही संचालन के लिए एक वैश्विक चर का उपयोग आवश्यक नहीं है, मैं सुझाव दूंगा कि उन चर को समारोह में स्थानीय घोषित किया जाए, जैसे:
(defun c:pointnumber ( / ic inr md nr ph point px sc ) ;; Local variables
;; ...
)
5. ब्लॉक अस्तित्व की जाँच करना
ब्लॉक नाम को सीधे INSERTकमांड पर मान लेना कि या तो उस ब्लॉक की एक परिभाषा पहले से ही सक्रिय ड्राइंग के भीतर मौजूद है, या कि फ़ाइल नाम के साथ एक ड्राइंग या तो कार्यशील निर्देशिका या ऑटोकैड समर्थन फ़ाइल खोज पथ के भीतर मौजूद है - यदि कोई शर्त पूरी नहीं हुई है, INSERTआदेश प्रोग्राम निष्पादन के दौरान त्रुटि होगा।
इसलिए आप पहले से इन स्थितियों का परीक्षण कर सकते हैं, यदि ब्लॉक नहीं मिला है, तो उपयोगकर्ता को सूचित करें, अन्यथा शेष संचालन को निष्पादित करने के लिए आगे बढ़ें:
(if
(or
(tblsearch "block" "pointnumber") ;; Checks for existing definition
(findfile "pointnumber.dwg") ;; Checks for drawing file
)
;; ...
)
आप अभिव्यक्तियों के cond
अनुक्रम के स्थान पर फ़ंक्शन का उपयोग कर सकते हैं if/else
।
6. एरर पर पर्यावरण को रीसेट करना
चूंकि आप प्रोग्राम निष्पादन के दौरान सिस्टम वैरिएबल मान बदल रहे हैं, तो आपको यह सुनिश्चित करना चाहिए कि प्रोग्राम के निष्पादन के दौरान त्रुटि होने की स्थिति में उपयोगकर्ता का ऑटोकैड वातावरण अपनी मूल स्थिति पर रीसेट हो जाए - यह देखते हुए कि Escप्रोग्राम से बाहर निकलने के लिए दबाव डालने वाला उपयोगकर्ता भी परिणाम देगा त्रुटि।
आप स्थानीय त्रुटि हैंडलर को परिभाषित करके इसे पूरा कर सकते हैं, जैसा कि मैंने त्रुटि हैंडलिंग पर अपने ट्यूटोरियल में वर्णन किया है । स्थानीय त्रुटि फ़ंक्शन का मूल्यांकन किया जाता है यदि प्रोग्राम निष्पादन के दौरान कोई त्रुटि होती है, और इसलिए आप ऑटोकैड वातावरण को इसकी मूल स्थिति में रीसेट करने के लिए इस फ़ंक्शन की परिभाषा में अभिव्यक्तियों को शामिल कर सकते हैं - आपके मामले में, इसमें मूल मान रीसेट करना शामिल होगा। ATTDIA
सिस्टम चर।
यह सब एक साथ डालें
;; Define function, declare local variables
(defun c:pointnumber ( / *error* bn ic nr ns pt px sc vl vr )
;; Define local error function to reset system variables on error
(defun *error* ( msg )
(mapcar 'setvar vr vl) ;; Reset list of system variables
(if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
(princ (strcat "\nError: " msg))
) ;; end if
(princ)
) ;; end defun
;; Define block name
(setq bn "pointnumber")
(if (or (tblsearch "block" bn) ;; Definition in drawing
(findfile (strcat bn ".dwg")) ;; Drawing file in support path
) ;; end or
(progn
(initget 6) ;; Prevents 0 & negatives
(setq sc (cond ((getreal "\nSpecify scale <1.0>: ")) (1.0))
px (getstring "\nSpecify prefix <none>: ")
) ;; end setq
(initget 4) ;; Prevents negatives
(setq nr (cond ((getint "\nSpecify starting number <1>: ")) (1)))
(initget 6) ;; Prevents 0 & negatives
(setq ic (cond ((getint "\nSpecify increment <1>: ")) (1)))
(setq vr '(attreq attdia cmdecho) ;; List of system variables
vl (mapcar 'getvar vr) ;; Store current values
) ;; end setq
(mapcar 'setvar vr '(1 0 0)) ;; Set system variables appropriately
(while (setq pt (getpoint "\nSpecify point <exit>: "))
(setq ns (itoa nr)
nr (+ nr ic)
)
(repeat (- 3 (strlen ns)) (setq ns (strcat "0" ns))) ;; Pad to 3 digits
(command "_.-insert" bn "_S" sc "_R" "0" "_non" pt (strcat px ns))
) ;; end while
(mapcar 'setvar vr vl) ;; Reset list of system variables to their original values
) ;; end progn
;; Else the block was not defined/found
(princ (strcat "\nThe block \"" bn "\" is not defined in the active drawing and cannot be found."))
) ;; end if
(princ) ;; Suppress the value returned by the last evaluated expression
) ;; end defun
अन्य संभावित सुधार हैं जिन्हें लागू किया जा सकता है, जैसे:
INSERTActiveX
insertblock
विधि या ड्राइंग डेटाबेस में सीधे DXF डेटा लिखने के लिएentmake
/entmakex
फ़ंक्शंस के उपयोग के माध्यम से मानक ऑटोकैड कमांड (इस मामले में कमांड) पर कॉल पर निर्भरता को हटा दें।अपने विशेषता टैग नामों को संदर्भित करके विशेषताओं को पॉप्युलेट करना ताकि ब्लॉक संदर्भ के भीतर विशेषता संदर्भों का सामना करना पड़ता है, जो उस आदेश पर निर्भरता को दूर करने के लिए है (जिसे BATTMANकमांड के उपयोग के माध्यम से प्रति-ड्राइंग के आधार पर संशोधित किया जा सकता है )।
'डायनेमिक डिफ़ॉल्ट' (जैसा कि मेरे ट्यूटोरियल में वर्णित है ) का उपयोग करना, और संभवतः ड्राइंग सत्रों के बीच चूक के मूल्य को संग्रहीत करना।