Adding objects in a batch

Discussion forum for contributors and developers who are using the QCAD version 3 ECMAScript development platform or the C++ plugin interface or who are otherwise looking to contribute to QCAD (translations, documentation, etc).

Moderator: andrew

Adding objects in a batch

Postby hungerburg » Mon Feb 06, 2012 4:03 pm

In my scripts I add objects one primitive by one primitive. They execute quite fast. Still I want to ask:

For performance reasons, can one join several RAddObject Operations into one RAddObjects Operation? When I switch layers inbetween those, will the entities end up in the right ones then? Or does qcad optimze already?
User avatar
hungerburg
Senior Member
 
Posts: 129
Joined: Fri May 28, 2010 7:35 pm

Postby andrew » Sun Feb 12, 2012 8:54 pm

Yes, you can add multiple objects in one transaction. Setting the current to a different takes effect immediately and is not part of the transaction (i.e. changing the current layer cannot be undone).
User avatar
andrew
Site Admin
 
Posts: 3188
Joined: Fri Mar 30, 2007 6:07 am

Postby hungerburg » Tue Feb 14, 2012 4:59 pm

Seems I am a little confused by RAddObjectsOperation and RAddObjectOperation. In fact I only use the first plural one and never the second singular one.

These operations I call from helper functions, that draw geometric primitives, that create both operation and objects internally only.

Code: Select all
   var operation = new RAddObjectsOperation(false);
   var linie = new RLineData(linien[l][0], linien[l][1]);
   var entity = new RLineEntity(zeichnung.document, linie);
   operation.addObject(entity);
   zeichnung.documentInterface.applyOperation(operation);


If instead I kept on adding objects to the operation, and applied it only later, then would all objects end up in the same layer? Or in the layer, that was active, at the time they were added to the operation? Could it be about useCurrentAttributes?

I know it is trivial to find out myself, but I am lazy right now, please excuse the many words too, but maybe its interesting for others too. It may prove a performance benefit, especially when the script runs in the GUI.
User avatar
hungerburg
Senior Member
 
Posts: 129
Joined: Fri May 28, 2010 7:35 pm

Postby andrew » Tue Feb 14, 2012 8:41 pm

hungerburg wrote:If instead I kept on adding objects to the operation, and applied it only later, then would all objects end up in the same layer? Or in the layer, that was active, at the time they were added to the operation? Could it be about useCurrentAttributes?


To the layer that was the current layer when the object was added if 'useCurrentAttributes' is true (default) or to the layer explicitly set on the entity (setLayer(...)) if 'useCurrentAttributes' is false.
User avatar
andrew
Site Admin
 
Posts: 3188
Joined: Fri Mar 30, 2007 6:07 am

Postby hungerburg » Wed Feb 15, 2012 5:11 pm

Thank You Andrew, with this information I started to refactor. I nearly gave in, as everything would end up in the same layer. But now it works :)

Code: Select all
var operation = new RAddObjectsOperation(false); // not undo-able
document.setCurrentLayer("A");
// […] create some entity
operation.addObject(entity, false); // stick it to current layer
document.setCurrentLayer("B");
// […] add some more objects to the operation
operation.addObject(entity, false); // stick it to current layer
// […] add some more objects to the operation
documentInterface.applyOperation(operation);

The useCurrentAttributes flag works like this:
    false: use attributes current at the time of the "add"
    true: use attributes current at the time of the "apply"

The performance gain is not noticeable though in command line mode or in linux GUI. I will see in windows GUI, because that is a little sluggish, when running scripts, compared to the linux one. Maybe that is only the grafics card though…
User avatar
hungerburg
Senior Member
 
Posts: 129
Joined: Fri May 28, 2010 7:35 pm

Re: Adding objects in a batch

Postby smf » Thu Jan 15, 2015 11:20 am

Hi Andrew,

this is an old thread, I know... But I think, my question belongs to it.

I'm trying to insert (copies of) several (sub-)entities. So I tried:
Code: Select all
    for (var j = 0; j < subIds.length; j++) {
      var sub = document.queryEntity(subIds[j]);
      var clone = sub.clone();
      clone.move(this.pos);
      //no changes with: storage.setObjectId(clone, RObject.INVALID_ID);
      //no changes with: clone.setLayerId(sub.getLayerId());
      op.addObject(clone, false); //nothing is ever inserted
      //this is working but entity is on wrong layer with: op.addObject(clone, true);
    }


Insertion with useCurrentAttributes==true works, but is not what is wanted. Insertion with useCurrentAttributes==false does not insert anything. I tried to use setObjectId(...INVALID) and to set LayerId manually, but that does not change anything. What am I doing wrong?

Thanks in advance :)
smf
Premier Member
 
Posts: 158
Joined: Tue Feb 28, 2012 1:05 pm

Re: Adding objects in a batch

Postby andrew » Thu Jan 15, 2015 11:50 am

Can you pst a bit more code (what operation are you using, how do you apply the operation), thanks.
User avatar
andrew
Site Admin
 
Posts: 3188
Joined: Fri Mar 30, 2007 6:07 am

Re: Adding objects in a batch

Postby smf » Thu Jan 15, 2015 11:58 am

Thanks for the fast reaction. :) I have a script that has a block-id in this.blockId. The complete getOperation function is

InsertExplodedBlock.prototype.getOperation = function(preview) {
var document = this.getDocument();
if (isNull(document)) {
return undefined;
}
var storage = document.getStorage(); //needed only for inserted "storage.setObjectId(clone, RObject.INVALID_ID);"

var op = new RAddObjectsOperation();
var block = document.queryBlock(this.blockId);
if (isNull(block)) {
EAction.handleUserMessage("internal error");
this.setState(-1);
this.terminate();
return;
}
var subIds = document.queryBlockEntities(this.blockId);
for (var j = 0; j < subIds.length; j++) {
var sub = document.queryEntity(subIds[j]);
var clone = sub.clone();
clone.move(this.pos);
op.addObject(clone, false);
}

return op;
};



The getOperation is called "as usual" by pickCoordinate:
InsertExplodedBlock.prototype.pickCoordinate = function(event, preview) {
var di = this.getDocumentInterface();
var document = this.getDocument();
this.pos = event.getModelPosition();
var op;

switch (this.state) {
case InsertExplodedBlock.State.SettingDestination:
if (preview) {
this.updatePreview();
}
else {
op = this.getOperation(false);
if (op == undefined) {
break;
}
di.applyOperation(op);
di.setRelativeZero(this.pos);
this.setState(-1);
this.terminate();
}
break;
}
};
smf
Premier Member
 
Posts: 158
Joined: Tue Feb 28, 2012 1:05 pm

Re: Adding objects in a batch

Postby andrew » Thu Jan 15, 2015 2:00 pm

op.addObject(obj, false) inserts the object onto the same layer, into the same block as the original. If I understand the intention correctly, you want to insert the clone into the current block instead (?).
In this case, set the blockId of the clone to the current blockId and use op.addObject(obj, true) instead.
User avatar
andrew
Site Admin
 
Posts: 3188
Joined: Fri Mar 30, 2007 6:07 am

Re: Adding objects in a batch

Postby smf » Thu Jan 15, 2015 3:21 pm

andrew wrote:into the same block as the original
and
andrew wrote:you want to insert the clone into the current block instead

Yes, that's the point. I want to insert all entities onto the original layer but the current block.

andrew wrote:set the blockId of the clone to the current blockId and use op.addObject(obj, true) instead.

Thank you very much, this was it. With addO..true it didn't worked, but with addO..false. :D Now the code is:
Code: Select all
    var currentBlockId = document.getCurrentBlockId();
    var op = new RAddObjectsOperation();
    var subIds = document.queryBlockEntities(this.blockId);
    if (isNull(subIds)) {
      EAction.handleUserMessage("internal error");
      this.setState(-1);
      this.terminate();
      return;
    }
    for (var j = 0; j < subIds.length; j++) {
      var sub = document.queryEntity(subIds[j]);
      var clone = sub.clone();
      clone.setBlockId(currentBlockId);
      clone.move(this.pos);
      op.addObject(clone, false);
    }


Thanks again for the perfect support! :D
smf
Premier Member
 
Posts: 158
Joined: Tue Feb 28, 2012 1:05 pm

Re: Adding objects in a batch

Postby smf » Sun Jan 18, 2015 10:33 am

...with the code above, the original entities are removed from the original block. After inserting "storage.setObjectId(clone, RObject.INVALID_ID)" it works as desired. :)
smf
Premier Member
 
Posts: 158
Joined: Tue Feb 28, 2012 1:05 pm


Return to QCAD 3 Developers and Contributors

Who is online

Users browsing this forum: No registered users and 2 guests