Author Topic: (entprev)  (Read 55602 times)

0 Members and 1 Guest are viewing this topic.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #105 on: November 27, 2013, 05:02:20 PM »
I have a built-in part of the code of VovKa "(assoc 360 (reverse EntOut)", now it works in Bricscad:

Code: [Select]
; Version 3.20 - 2013/11/27
(defun ALE_EntPrevious (EntNam / SelSet EntDat Countr EntOut PrnEnt)
  (if
    (and
      (assoc 410 (setq EntDat (entget EntNam)))
      (not (wcmatch (cdr (assoc 0 EntDat)) "ATTRIB,VERTEX"))
    )
    (progn
      (setq SelSet (ssget "_X")   Countr 0)
      (while SelSet
        (if (eq EntNam (ssname SelSet Countr))
          (setq EntOut (ssname SelSet (1+ Countr))  PrnEnt EntOut  SelSet nil)
          (setq Countr (1+ Countr))
        )
      )
    )
    (setq
      EntOut (entget (cdr (assoc 330 EntDat)))
      EntOut (cdr (cond ((assoc 360 (reverse EntOut)))
                         ((assoc -1 EntOut))
                  )
             )
    )
  )
  (while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
    (setq EntOut PrnEnt)
  )
  EntOut
)

But:
Code: [Select]
(defun entprev (e / e1 e2)
  (setq    e1 (entget (cdr (assoc 330 (entget e))))
    e1 (cdr    (cond ((assoc 360 (reverse e1)))
              ((assoc -1 e1))
        )
       )
  )
  (while (and e1 (not (eq e (setq e2 (entnext e1)))))
    (setq e1 e2)
  )
  e1
)

>>> Bricscad command line:
Code: [Select]
: (entprev         EntRef)

; ----- Error around expression -----
(ENTNEXT E1)
;
; error : Unknown Error in Lisp or CAD system or 'Stack Overflow'

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #106 on: November 28, 2013, 02:34:14 AM »
...
OK I have to fix my code, here it is again -
...
Luis, if I select a block ATTRIB I get an error:
Code: [Select]
(defun c:Test2 ( / EntRef EntPrv)
(setq EntRef (car (nentsel)))
(princ "\nEntRef         ") (princ EntRef)
(princ "\nALE_EntPrevious") (princ (entnext (setq EntPrv (ALE_EntPrevious EntRef))))
(princ "\nentprev        ") (princ (entnext (setq EntPrv (entprev         EntRef))))
(princ "\nentpreviousFrom") (princ (entnext (setq EntPrv (entpreviousFrom EntRef)))) ; louis
(textpage)(princ)
)
Select object:
EntRef         <Entity name: 7ffffb5fd20>
ALE_EntPrevious<Entity name: 7ffffb5fd20>
entprev        <Entity name: 7ffffb5fd20>
entpreviousFrom; error: bad argument type: lentityp nil

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #107 on: November 28, 2013, 03:01:43 AM »
Selection sets may be influenced by the Layouts, I don't truly know, but that's not the point of this thread is it?
But I do know that entnext and entlast is not affected by them at all.
...
perhaps this thread may be interesting:
http://forums.autodesk.com/t5/Visual-LISP-AutoLISP-and-General/Copy-order-of-entities/td-p/1557265/page/3

Do you think that the format for saving a DWG can change the way of operate?
(I normally work with 2013 but save in 2004 version)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: (entprev)
« Reply #108 on: November 28, 2013, 03:35:13 AM »
...and where is "TEXT on Layout2"?
:? oops yes, you're correct! Only the last opened PS tab is iterated by entnext. So it's a situation of the model space object and the current paper space object.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #109 on: November 28, 2013, 06:09:30 AM »
Simple DWG, draw: 1 circle on ModelSpace + 1 circle on layout1 + 1 circle on layout2
Code: [Select]
Command: (ale_entprevious (entnext (entnext)))
<Entity name: 7ffffbfc330>

Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>

Command: CTAB

Enter new value for CTAB <"Layout2">: layout1
Restoring cached viewports - Regenerating layout.

Command: (ale_entprevious (entnext (entnext)))
nil

Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>

Command: (entnext)
<Entity name: 7ffffbfc330>

Command: CTAB

Enter new value for CTAB <"Layout1">: model
Restoring cached viewports.

Command: (ale_entprevious (entnext (entnext)))
nil

Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>

Command: (entnext)
<Entity name: 7ffffbfc330>

;;; switch to layout2 then to model

Command: CTAB

Enter new value for CTAB <"Model">: layout2
Restoring cached viewports - Regenerating layout.

Command: CTAB

Enter new value for CTAB <"Layout2">: model
Restoring cached viewports.

Command: (ale_entprevious (entnext (entnext)))
<Entity name: 7ffffbfc330>

Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>
...and where is "TEXT on Layout2"?
:? oops yes, you're correct! Only the last opened PS tab is iterated by entnext. So it's a situation of the model space object and the current paper space object.
This is the reason why entprev is very fast if there are many layout with many entities.
And, from help:
 "If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in the database.
Code: [Select]
Command: (ale_entprevious (entnext)) => nil
Command: (entprev (entnext))         => <Entity name: 7ffffbf9950>

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: (entprev)
« Reply #110 on: November 28, 2013, 07:07:59 AM »
"If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in the database.
Ah! But that's then not strictly true is it? E.g. blank drawing (all VP's deleted) with a circle on Layout2 with Layout1 open. (entnext) will give you the "Viewport" which is actually Layout1's page. But if you later draw a line in model space - that is considered the "1st" (not the VP, nor the circle).

Thus it should rather read as: "If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in either the model space or the current paperspace. If none found in model space, then the paperspace page (not viewport) is the 1st found. If the MS was blank before drawing anything in any PS, then any later entities in MS will be considered prior to the existing entities in the PS. Only after MS contains something is the order of entities constant. If you then delete the MS contents, the VP of PS becomes the 1st entity - even if you then draw something new in MS. When you then swap to a different PS the MS items are interpreted as previous to anything on the new PS (even if they were drawn earlier)"

It seems these edge cases might need lots of checks to get entprev working as an exact inverse of entnext.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

LE3

  • Guest
Re: (entprev)
« Reply #111 on: November 28, 2013, 12:02:09 PM »
Code: [Select]
[quote author=Marc'Antonio Alessi link=topic=45732.msg509089#msg509089 date=1385624054]
Luis, if I select a block ATTRIB I get an error:
entpreviousFrom; error: bad argument type: lentityp nil
[/quote]

Marco,
Looks like we need to add more conditions like what I have in there now and test for the selection type:
Quote
if (pObj->isKindOf(AcDb2dVertex::desc()))

I have a long weekend here, starting today, so I can play with this.

Thanks,
LE!

PS> Can you upload your test drawing with the block? - thanks!
« Last Edit: November 28, 2013, 12:18:02 PM by LE »

LE3

  • Guest
Re: (entprev)
« Reply #112 on: November 28, 2013, 02:03:00 PM »
Code: [Select]
[quote author=Marc'Antonio Alessi link=topic=45732.msg509089#msg509089 date=1385624054]
entpreviousFrom; error: bad argument type: lentityp nil

I think I have my code fixed/updated and now will return the previous entity from these type of selections (will uploaded in a while/later need more tests).

please... ignore my previous comment --- all work.
« Last Edit: November 28, 2013, 03:12:28 PM by LE »

LE3

  • Guest
Re: (entprev)
« Reply #113 on: November 28, 2013, 04:42:41 PM »
Here it is my latest code:

Code - C++: [Select]
  1. static int ads_EntPreviousFrom(void)
  2. {
  3.         struct resbuf *rb = acedGetArgs();
  4.         if (!rb)
  5.         {
  6.                 acutPrintf(_T("\nError: function requires an ENAME argument. \n"));
  7.                 return RSERR;
  8.         }
  9.         AcDbObjectId objId;
  10.         ads_name objName;
  11.         if (rb && (rb->restype == RTENAME))
  12.         {
  13.                 if (acdbGetObjectId(objId, rb->resval.rlname) == Acad::eOk)
  14.                 {
  15.                         AcDbObjectPointer<AcDbEntity> pObj(objId, AcDb::kForRead);
  16.                         if (pObj.openStatus() == Acad::eOk)
  17.                         {
  18.                                 if (pObj->isKindOf(AcDb2dVertex::desc()))
  19.                                 {
  20.                                         AcDbObjectPointer<AcDb2dPolyline> pPline(pObj->ownerId(), AcDb::kForRead);
  21.                                         if (pPline.openStatus() == Acad::eOk)
  22.                                         {
  23.                                                 AcDbObjectIterator* pVertIterator = pPline->vertexIterator();
  24.                                                 pVertIterator->start();
  25.                                                 pVertIterator->setPosition(pObj->objectId());
  26.                                                 pVertIterator->step(true);
  27.                                                 AcDbObjectPointer<AcDb2dVertex> pVertex(pVertIterator->objectId(), AcDb::kForRead);
  28.                                                 if (pVertex.openStatus() == Acad::eOk)
  29.                                                 {
  30.                                                         if (acdbGetAdsName(objName, pVertex->objectId()) == Acad::eOk)
  31.                                                         {
  32.                                                                 acedRetName(objName, RTENAME);
  33.                                                         }
  34.                                                 }
  35.                                                 else if (acdbGetAdsName(objName, pPline->objectId()) == Acad::eOk)
  36.                                                 {
  37.                                                         acedRetName(objName, RTENAME);
  38.                                                 }
  39.                                                 delete pVertIterator;
  40.                                         }
  41.                                 }
  42.                                 else if (pObj->isKindOf(AcDbAttribute::desc()))
  43.                                 {
  44.                                         AcDbObjectPointer<AcDbBlockReference> pRef(pObj->ownerId(), AcDb::kForRead);
  45.                                         if (pRef.openStatus() == Acad::eOk)
  46.                                         {
  47.                                                 AcDbObjectIterator* pAttributeIterator = pRef->attributeIterator();
  48.                                                 pAttributeIterator->start(true);
  49.                                                 pAttributeIterator->setPosition(pObj->objectId());
  50.                                                 pAttributeIterator->step(true);
  51.                                                 AcDbObjectPointer<AcDbAttribute> pAttribute(pAttributeIterator->objectId(), AcDb::kForRead);
  52.                                                 if (pAttribute.openStatus() == Acad::eOk)
  53.                                                 {
  54.                                                         if (acdbGetAdsName(objName, pAttribute->objectId()) == Acad::eOk)
  55.                                                         {
  56.                                                                 acedRetName(objName, RTENAME);
  57.                                                         }
  58.                                                 }
  59.                                                 else if (acdbGetAdsName(objName, pRef->objectId()) == Acad::eOk)
  60.                                                 {
  61.                                                         acedRetName(objName, RTENAME);
  62.                                                 }
  63.                                                 delete pAttributeIterator;
  64.                                         }
  65.                                 }
  66.                                 else
  67.                                 {
  68.                                         AcDbBlockTableRecordPointer pBTR(pObj->ownerId(), AcDb::kForRead);
  69.                                         if (pBTR.openStatus() == Acad::eOk)
  70.                                         {
  71.                                                 AcDbBlockTableRecordIterator* pIterator = NULL;
  72.                                                 if (pBTR->newIterator(pIterator) == Acad::eOk)
  73.                                                 {
  74.                                                         AcDbEntity* pEnt = NULL;
  75.                                                         if (pIterator->seek(pObj) == Acad::eOk)
  76.                                                         {
  77.                                                                 pIterator->step(false, true);
  78.                                                                 AcDbObjectId objId;
  79.                                                                 pIterator->getEntityId(objId);
  80.                                                                 AcDbObjectPointer<AcDbEntity> pEnt(objId, AcDb::kForRead);
  81.                                                                 if (pEnt.openStatus() == Acad::eOk)
  82.                                                                 {
  83.                                                                         if (acdbGetAdsName(objName, objId) == Acad::eOk)
  84.                                                                         {
  85.                                                                                 acedRetName(objName, RTENAME);
  86.                                                                         }
  87.                                                                 }
  88.                                                         }
  89.                                                         delete pIterator;
  90.                                                 }
  91.                                         }
  92.                                 }
  93.                         }
  94.                 }
  95.         }
  96.         return (RSRSLT);
  97. }
  98.  

I see on my tests that the ALE_EntPrevious and entprev on a drawing with some entities and one dimension, if I select (nested) the mtext of the dimension, and then I get all the previous entities, it will stop (return nil) after an ACAD BLOCK or AcDbBlockBegin and any previous entities won't be scanned.

This (coding) is fun!

Let's see if works (arx attached).

TODO: Next task need to study AcDbDimension(s)... and being able to do the scan back.....the seek() works on the iterator but somehow the step back or something is not working... hmm need to install the arx wizard right since the debug does not work and can't step into each line..... :-(
« Last Edit: November 28, 2013, 04:58:24 PM by LE »

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: (entprev)
« Reply #114 on: November 28, 2013, 06:07:11 PM »
"If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in the database.
Ah! But that's then not strictly true is it? E.g. blank drawing (all VP's deleted) with a circle on Layout2 with Layout1 open. (entnext) will give you the "Viewport" which is actually Layout1's page. But if you later draw a line in model space - that is considered the "1st" (not the VP, nor the circle).

Thus it should rather read as: "If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in either the model space or the current paperspace. If none found in model space, then the paperspace page (not viewport) is the 1st found. If the MS was blank before drawing anything in any PS, then any later entities in MS will be considered prior to the existing entities in the PS. Only after MS contains something is the order of entities constant. If you then delete the MS contents, the VP of PS becomes the 1st entity - even if you then draw something new in MS. When you then swap to a different PS the MS items are interpreted as previous to anything on the new PS (even if they were drawn earlier)"

It seems these edge cases might need lots of checks to get entprev working as an exact inverse of entnext.

Yes, Irne, (entprev) will be very hard to implement doing exact inverse of (entnext)... So I take back my words... Given the fact that ALISP is equipped with saver function (entlast)... We can easily do it instead (entprev (entprev)) as (entprev (entlast)), due to the fact that I don't know how to construct function (entprev) to perform with and without supplied argument and not to actually change (defun's) names... So if this level of problem can be solved than (entprev) can be exact what should, but as we can see there is (entlast) alternative...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #115 on: November 30, 2013, 04:54:52 AM »
Here it is my latest code:
...
Let's see if works (arx attached).

TODO: Next task need to study AcDbDimension(s)... and being able to do the scan back.....the seek() works on the iterator but somehow the step back or something is not working... hmm need to install the arx wizard right since the debug does not work and can't step into each line..... :(
Sorry for late:
Code: [Select]
Benchmark.lsp | © 2005 Michael Puckett | All Rights Reserved
Elapsed milliseconds / relative speed for 16384 iteration(s):

> Old Polyline
    (entpreviousfrom KKKK).....1607 / 1.31 <fastest>
    (ALE_ENTPREVIOUS KKKK).....2106 / 1 <slowest>

> Entity in block
    (entpreviousfrom KKKK)......2246 / 28.48 <fastest>
    (ALE_ENTPREVIOUS KKKK).....63976 / 1 <slowest>
   
> Attrib in Block
    (entpreviousfrom KKKK).....1092 / 1.53 <fastest>
    (ALE_ENTPREVIOUS KKKK).....1669 / 1 <slowest>

> Line                       ********
    (entpreviousfrom KKKK).......1029 / 167.57 <fastest>
    (ALE_ENTPREVIOUS KKKK).....172428 / 1 <slowest>
   
Yes, if I select a dimension nested entity (maybe the first or the last)
I get an error.

But sometime I get a wrong result similar with entprev (VovKa):   

Code: [Select]
Command: !entref
<Entity name: 7ffffbb3550>

Command: (entnext (ALE_EntPrevious EntRef))
<Entity name: 7ffffbb3550>

Command: (entnext (entprev         EntRef))
<Entity name: 7ffffbb3550>

Command: (entnext (entpreviousFrom EntRef))
<Entity name: 7ffffbb32e0>

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #116 on: November 30, 2013, 04:59:14 AM »
...
Yes, Irne, (entprev) will be very hard to implement doing exact inverse of (entnext)...

Do you know a condition for the last ALE_ENTPREVIOUS do not get the exact inverse of (entnext)?

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: (entprev)
« Reply #117 on: November 30, 2013, 07:58:27 AM »
...
Yes, Irne, (entprev) will be very hard to implement doing exact inverse of (entnext)...

Do you know a condition for the last ALE_ENTPREVIOUS do not get the exact inverse of (entnext)?

Marc' I think your version has even advantage in comparison to (entprev) my last version I posted... The only difference I see in obraining result is the case where you actually pick with (ale_entprevious (car (nentsel))) first nested entity in block - it then returns "BLOCK" entity - BlockBegin... And my version (entprev (car (nentsel))) with picked first nested entity returns nil - similar to picking last nested entity inside block or dimension with (entnext (car (nentsel)))... I've checked the cases with paper/model space entities and both version act the same (so I don't know how did you get these results stated in post 109) :
Code: [Select]
Command: CTAB

Enter new value for CTAB <"Layout2">: layout1
Restoring cached viewports - Regenerating layout.

Command: (ale_entprevious (entnext (entnext)))
nil

Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>
When I checked I get entity name of first imaginary VIEWPORT entity that is base entity of Layout TAB...
I don't quite know how would benchmarking show results between these 2 variants, as I think that your version is better optimized if DWG contains entities consisted from vertices or attribs... We should check comparison of these 2 in large amount of entities with those properties, but for checking choosing just the entity that is in the middle of (ssget "_X") - I mean (ssname (ssget "_X") (1- (fix (/ (sslength (ssget "_X") 2.0))))...

So long from me and thanks Marc' for your inputs... Don't take this too serious this all topic was intended for experimental purposes... I mean should new function be implemented into AutoLisp, this all falls to water as probably fastest solution would be implemented and the one that is seriously tested...

As I did wrote, your version seems to me just fine for now and I should be using it for my purposes if I get the opportunity for using it in the future (until and if Autodesk plans to upgrade existing functions database come into reality)...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: (entprev)
« Reply #118 on: November 30, 2013, 08:43:02 AM »
...
Marc' I think your version has even advantage in comparison to (entprev) my last version I posted... The only difference I see in obraining result is the case where you actually pick with (ale_entprevious (car (nentsel))) first nested entity in block - it then returns "BLOCK" entity - BlockBegin... And my version (entprev (car (nentsel))) with picked first nested entity returns nil - similar to picking last nested entity inside block or dimension with (entnext (car (nentsel)))... I've checked the cases with paper/model space entities and both version act the same (so I don't know how did you get these results stated in post 109) :
...
Marko,

sorry but I never test your functions, I do not like to test functions with the same name of others.
For me "entprev" is the function written by VovKa.

If I test your last version (renamed from entprev to entprevMR):
Code: [Select]
(defun entprevMR (e / e1 e2)
 (if (eq (type e) 'ename)
   (if (eq e (entnext))
     nil
     (progn
       (if (not
             (or
               (eq (cdr (assoc 2 (entget (cdr (assoc 330 (entget e)))))) "*Model_Space")
               (eq (cdr (assoc 2 (entget (cdr (assoc 330 (entget e)))))) "*Paper_Space")
             )
           )
         (progn
           (setq e1 (cdr (assoc -2 (entget (cdr (assoc 360 (entget (cdr (assoc 330 (entget e))))))))))
           (if (eq e e1) nil
             (progn
               (while (and e1 (not (eq e (setq e2 (entnext e1)))))
                 (setq e1 e2)
               )
               e1
             )
           )
         )
         (progn
           (setq e1 (entnext))
           (while (and e1 (not (eq e (setq e2 (entnext e1)))))
             (setq e1 e2)
           )
           e1
         )
       )
     )
   )
   (entget e)
 )
)
Test on my last DWG posted:
Code: [Select]
; select line 1
Comando: (setq EntRef (car (nentsel)))
Selezionare oggetto: <Nome entità: 7ffffb600b0>
Comando: (entprevMR EntRef)
nil                            <<< NOT TRUE


; select line 2 in block
Comando: (setq EntRef (car (nentsel)))
Selezionare oggetto: <Nome entità: 7ffffb18770>
Comando: (entprevMR EntRef)
<Nome entità: 7ffffb18760>
Comando: (entnext (entprevMR EntRef))
<Nome entità: 7ffffb18770>      <<< TRUE


; select OLD polyline 3
Comando: (setq EntRef (car (nentsel)))
Selezionare oggetto: <Nome entità: 7ffffb5fde0>
Comando: (entprevMR EntRef)
; errore: tipo di argomento errato: lentityp nil

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: (entprev)
« Reply #119 on: November 30, 2013, 10:22:50 AM »
Sorry, Marc'... I thought my code will work on old POLYLINE vertices...

Here is the version for tests... Although I think your code will perform faster in the case I described above... (ssname (ssget "_X") (1- (fix (/ (sslength (ssget "_X")) 2.0))))

Code - Auto/Visual Lisp: [Select]
  1. (defun entprev (e / e1 e2)
  2.   (if (eq (type e) 'ename)
  3.     (if (eq e (entnext))
  4.       nil
  5.       (if (wcmatch (cdr (assoc 0 (entget e))) "ATTRIB,VERTEX,SEQEND")
  6.         (progn
  7.           (setq e1 (cdr (assoc 330 (entget e))))
  8.           (while (and e1 (not (eq e (setq e2 (entnext e1)))))
  9.             (setq e1 e2)
  10.           )
  11.           e1
  12.         )
  13.         (if
  14.           (not
  15.             (or
  16.               (eq (cdr (assoc 2 (entget (cdr (assoc 330 (entget e)))))) "*Model_Space")
  17.               (eq (cdr (assoc 2 (entget (cdr (assoc 330 (entget e)))))) "*Paper_Space")
  18.             )
  19.           )
  20.            (progn
  21.              (setq e1 (tblobjname "BLOCK" (vla-get-name (vlax-ename->vla-object (cdr (assoc 330 (entget e)))))))
  22.              (while (and e1 (not (eq e (setq e2 (entnext e1)))))
  23.                (setq e1 e2)
  24.              )
  25.              e1
  26.            )
  27.            (progn
  28.              (setq e1 (cdr (assoc 360 (reverse (entget (cdr (assoc 330 (entget e))))))))
  29.              (while (and e1 (not (eq e (setq e2 (entnext e1)))))
  30.                (setq e1 e2)
  31.              )
  32.              e1
  33.            )
  34.         )
  35.       )
  36.     )
  37.     (entget e)
  38.   )
  39. )
  40.  

My apology for wrong code...
M.R.
« Last Edit: December 01, 2013, 05:02:01 PM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube