Tutorial: Writing a plugin that draws a dovetail

Discussion forum for C++ and script developers who are using the QCAD development platform or who are looking to contribute to QCAD (translations, documentation, etc).

Moderator: andrew

Forum rules

Always indicate your operating system and QCAD version.

Attach drawing files, scripts and screenshots.

Post one question per topic.

Post Reply
matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Tutorial: Writing a plugin that draws a dovetail

Post by matthiaswm » Thu May 23, 2013 11:53 pm

OK, so this is how I write plugins. I write C++ code for thirtysome years, learned a few other languages and do some Reverse Engineering. That may or may not explain my approach here. I had no clue about Java Script until a few weeks ago. It's easy and powerful. You can learn it!

When extending functionality, I like to base my code on a working script and then change it the way I need, verifying my steps. So first we need to find an existing script that does 90% of what we want. Drawing a rectangle from point to point is good. After searching a bit, I found a directory: .../scripts/Draw/Line/LineRectangle/ . So lets duplicate the entire directory just where it is and name the new one "LineDove".

Go into the directory and rename the following files:

Code: Select all

  LineRectangle.svg, LineRectangleInit.js, LineRectangle.js
to 
  LineDove.svg, LineDoveInit.js, LineDove.js
LineDove.svg is the vector graphic for the icon in the toolbar. Leave it alone for now, or edit it, if you have time to spare.

LineDoveInit.js registers the script with the user interface. Open the file in a text editor (not MSWord! Just a plain and simple text editor) and replace all occurrences of LineRectangle with LineDove. Replace the word "&Rectangle" with "Dovetail", and change the setDefaulCommands. The code looks now like this:
function init(basePath) {
    var action = new RGuiAction(qsTranslate("LineDove", "&Rectangle"),
        RMainWindowQt.getMainWindow());
    action.setRequiresDocument(true);
    action.setScriptFile(basePath + "/LineDove.js");
    action.setIcon(basePath + "/LineDove.svg");
    action.setDefaultShortcut(new QKeySequence("r,v"));
    action.setStatusTip(qsTranslate("LineDove", "Draw a dovetail joint"));
    action.setDefaultCommands(["dovetail"]);
    action.setSortOrder(500);
    EAction.addGuiActionTo(action, Line, true, true, true, true);
}
LineDove.js contains the actual script. But let's first fix the names so that the original script may run. In the entire file, replace LineRectangle with LineDove. Now find the first line that contains new RVector. This line of code draws the first side of the rectangle. Replace the code snippet this.corner1.y with this.corner1.y/2 (divide the y coordinate of your first click by two).

Let's check if we did everything right!

Launch QCad and select Draw/Line. You should find *two* icons for drawing a rectangle. Try the first one and draw a rectangle. If you did everything right, you will now see a very quirky shape drawn. No dovetail yet, but at least we "wrote" our first plugin. To be continued... .

If anything went wrong and QCad is not launching anymore, or crashing or anything else, simply remove the directory we created earlier (".../scripts/Draw/Line/LineDove/"). Everything should be back to normal. Now try over ;-)
Last edited by matthiaswm on Sun Jun 02, 2013 8:10 pm, edited 1 time in total.

User avatar
Clive
Moderator
Posts: 1329
Joined: Thu Aug 25, 2011 9:28 pm
Location: UK

Re: Writing a plugin that draws a dovetail

Post by Clive » Fri May 24, 2013 9:19 am

Hi Matthias
This is exactly what I was talking about, your 'step by step' method is perfect. Explaining about the little things - no matter how basic they are is exactly what beginners to scripting in QCAD need.
Explaining what the different scripts do and what to change, then checking etc. etc.is brilliant and is very welcome. I will definitely try some of this out :wink:
matthiaswm wrote: No dovetail yet, but at least we "wrote" our first plugin. To be continued... .
Thank you so much for your time on this, looking forward to the next installment on this tutorial :D .

I'm hoping this will encourage others to add some 'scripting' tutorials for QCAD.

matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Re: Writing a plugin that draws a dovetail

Post by matthiaswm » Sat May 25, 2013 6:10 pm

Allright, now let's finish that birds rear. We need math!

The dimensions of a dovetail joint are not fixed, so I decided to make them symmetrical, allowing multiple fingers. If the tail is 12mm at the end, and 8mm at the base, I need 6mm to the left and right of the base which gives us a base with of 20mm. Let's then make the tail 8mm long to look proportional. Of course, the CAD program know nothing about Millimetrs or inches, so we need to use fractions to make everything based on the unit 1.

So here is the formula for drawing our dove tail, starting at the left, moving to the right, pointing to the top:
  • draw 6mm to the right (the base of the slot)
  • draw 2mm to the left and 8mm up (the first diagonal, shaping the tail)
  • draw 12mm to the right (the end of the tail)
  • draw 2mm to the left and 8mm down (the second diagonal)
  • draw 6mm to the right
OK, so if we add up the numbers and we put that in code, it reads:

Code: Select all

LineDove.prototype.getOperation = function(preview) {
    var corners = new Array(
        new RVector( 0, 0),
        new RVector( 6, 0),
        new RVector( 4, 8),
        new RVector(16, 8),
        new RVector(14, 0),
        new RVector(20, 0)
    );
    var op = new RAddObjectsOperation();
    for (var i=0; i<5; ++i) {
        var lineData = new RLineData(corners[i],corners[i+1]);
        var line = new RLineEntity(this.getDocument(), lineData);
        op.addObject(line);
    }
    return op;
};
Here is a trick for testing. If you are on Linux or OS X, start QCad from the command line with additional options. You will get diagnostic output, and you can modify and test the script without quitting and relaunching QCad. In OS X, the command line is:

Code: Select all

/Applications/QCAD.app/Contents/MacOS/QCAD -always-load-scripts
  or if you are adventurous:
/Applications/QCAD.app/Contents/MacOS/QCAD -always-load-scripts -enable-script-debugger
The code above is nice, but it only puts one very specific Dovetail at 0, 0. That should be more universal! To generate the Dovetail where we clicked the first time, we add the line line.move(this.corner1);.

Wait a minute! Ho did I find out about this magic function named move()? Ah, it's all in the manual. So line is of type RLineEntity. But if we go to the documentation of RLineEntity https://www.ribbonsoft.com/doc/qcad/3.0 ... mbers.html, there is no function named move(). However, RLineEntity is derived from REntity, meaning it can do anything that REntity can do plus more. Click on List of all members, and there it is: move https://www.ribbonsoft.com/doc/qcad/3.0 ... 1b52e8a745.

If we can move our list of vectors, we surely can rotate and scale it as well. So let's find out how long the dowetail should be, and at what angle we need to draw it:

Code: Select all

    var len = this.corner1.getDistanceTo(this.corner2);
    var ang = this.corner1.getAngleTo(this.corner2);
and we apply that to the vector list (remember that we need to scale by 1/20 because our initial calculations assumed a 20mm wide joint):

Code: Select all

LineDove.prototype.getOperation = function(preview) {
    var len = this.corner1.getDistanceTo(this.corner2);
    var ang = this.corner1.getAngleTo(this.corner2);
    var corners = new Array(
        new RVector( 0, 0),
        new RVector( 6, 0),
        new RVector( 4, 8),
        new RVector(16, 8),
        new RVector(14, 0),
        new RVector(20, 0)
    );
    var op = new RAddObjectsOperation();
    for (var i=0; i<5; ++i) {
        var lineData = new RLineData(corners[i],corners[i+1]);
        var line = new RLineEntity(this.getDocument(), lineData);
        line.scale(len/20);
        line.move(this.corner1);
        line.rotate(ang, this.corner1);
        op.addObject(line);
    }
    return op;
};
Tadaaa.... . ;-)

User avatar
Clive
Moderator
Posts: 1329
Joined: Thu Aug 25, 2011 9:28 pm
Location: UK

Re: Writing a plugin that draws a dovetail

Post by Clive » Sun May 26, 2013 9:59 am

Nice, thank you so much :D

User avatar
Husky
Moderator/Drawing Help/Testing
Posts: 4931
Joined: Wed May 11, 2011 9:25 am
Location: USA

Re: Tutorial: Writing a plugin that draws a dovetail

Post by Husky » Fri Jul 12, 2013 8:36 pm

Has somebody finished this Dove Tail Plug in? Would it be possible for a "non programmer" like me to download a working script for QCAD? :oops:

matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Re: Tutorial: Writing a plugin that draws a dovetail

Post by matthiaswm » Fri Jul 12, 2013 9:34 pm

Oh, sure. Here's the archive that you will need to unpack:

adding: scripts/Draw/Line/LineDove/
adding: scripts/Draw/Line/LineDove/LineDove.js
adding: scripts/Draw/Line/LineDove/LineDove.svg
adding: scripts/Draw/Line/LineDove/LineDoveInit.js

[Edit from andrew: please note that this script might be outdated. The latest version is available in all newer QCAD installations under Misc > Draw]
Attachments
LineDove.zip
(4.02 KiB) Downloaded 1801 times

User avatar
Husky
Moderator/Drawing Help/Testing
Posts: 4931
Joined: Wed May 11, 2011 9:25 am
Location: USA

Re: Tutorial: Writing a plugin that draws a dovetail

Post by Husky » Sat Jul 13, 2013 1:48 am

Very nice! Thank you! :D :D :D

User avatar
caigner
Full Member
Posts: 83
Joined: Wed Jan 30, 2013 5:24 pm
Location: Austria

Re: Tutorial: Writing a plugin that draws a dovetail

Post by caigner » Sun Jul 14, 2013 10:28 am

Indeed a very useful script. Thanks alot!

Because I use a router bit with 14° angle to cut the dovetail I modified the numbers slightly to achieve this angle:

Code: Select all

    var corners = new Array(
        new RVector( 0, 0),
        new RVector( 6, 0),
        new RVector( 4.0053759772545544670076804975611, 8),
        new RVector(15.994624022745445532992319502439, 8),
        new RVector(14, 0),
        new RVector(20, 0)
    );

matthiaswm
Junior Member
Posts: 24
Joined: Mon Apr 29, 2013 4:34 pm

Re: Tutorial: Writing a plugin that draws a dovetail

Post by matthiaswm » Sun Jul 14, 2013 12:16 pm

Sure, great! It's nice to see the script being used in real life, even though it was originally just a tutorial for writing scripts ;-)

One elegant way would be a parameter in the tool bar that takes the angle an diameter of the router bit and applies that to the drawing. Are you readers interested in that? When time permits, I can add that to the tutorial.

User avatar
Clive
Moderator
Posts: 1329
Joined: Thu Aug 25, 2011 9:28 pm
Location: UK

Re: Tutorial: Writing a plugin that draws a dovetail

Post by Clive » Sun Jul 14, 2013 1:11 pm

matthiaswm wrote:One elegant way would be a parameter in the tool bar that takes the angle an diameter of the router bit and applies that to the drawing. Are you readers interested in that? When time permits, I can add that to the tutorial.
Yes please, that would be great :wink: but of course in your own time.

User avatar
Husky
Moderator/Drawing Help/Testing
Posts: 4931
Joined: Wed May 11, 2011 9:25 am
Location: USA

Re: Tutorial: Writing a plugin that draws a dovetail

Post by Husky » Sun Jul 14, 2013 6:28 pm

clive wrote:
matthiaswm wrote:One elegant way would be a parameter in the tool bar that takes the angle an diameter of the router bit and applies that to the drawing. Are you readers interested in that? When time permits, I can add that to the tutorial.
Yes please, that would be great :wink: but of course in your own time.
Yes please, for me (us) too. :D
That's what I'm really looking for to be able to work with different settings for all kinds of dove tails .... without leaving the QCAD Program surface :wink:

User avatar
Husky
Moderator/Drawing Help/Testing
Posts: 4931
Joined: Wed May 11, 2011 9:25 am
Location: USA

Re: Tutorial: Writing a plugin that draws a dovetail

Post by Husky » Thu Aug 15, 2013 8:22 am

matthiaswm wrote:Oh, sure. Here's the archive that you will need to unpack:

adding: scripts/Draw/Line/LineDove/
adding: scripts/Draw/Line/LineDove/LineDove.js
adding: scripts/Draw/Line/LineDove/LineDove.svg
adding: scripts/Draw/Line/LineDove/LineDoveInit.js
Do you mind if I put your script (.zip) also in our new "QCAD 3 ' script Add-On & Plug-in challenge" Forum?
Just to make sure everybody will find it ..... :wink: :wink: :wink:

User avatar
caigner
Full Member
Posts: 83
Joined: Wed Jan 30, 2013 5:24 pm
Location: Austria

Re: Tutorial: Writing a plugin that draws a dovetail

Post by caigner » Wed Mar 04, 2015 8:26 am

matthiaswm wrote:One elegant way would be a parameter in the tool bar that takes the angle an diameter of the router bit and applies that to the drawing. Are you readers interested in that? When time permits, I can add that to the tutorial.
Hi Matthias!

A parameter for the angle in the toolbar would be a really great addition to this wonderful script. Could you? Would you? Please! :-)
I am using hand tools to cut dovetails and old woodworkers suggest different angles for different wood hardness.

Regards,
Christian
QCAD Pro on Gentoo Linux

User avatar
caigner
Full Member
Posts: 83
Joined: Wed Jan 30, 2013 5:24 pm
Location: Austria

Re: Tutorial: Writing a plugin that draws a dovetail

Post by caigner » Tue Feb 14, 2017 1:27 pm

I have given it a try to produce a script that will take number of dovetails, height of dovetails, dovetail/pin ratio and gradient.

Try as I might, I couldn't make it work, but I have posted my attempt here:

viewtopic.php?f=107&t=4737
QCAD Pro on Gentoo Linux

User avatar
caigner
Full Member
Posts: 83
Joined: Wed Jan 30, 2013 5:24 pm
Location: Austria

Re: Tutorial: Writing a plugin that draws a dovetail

Post by caigner » Thu Feb 16, 2017 1:03 pm

I finally did it!

For the new Dovetail Script please go to:

viewtopic.php?f=107&t=4737#p17410
QCAD Pro on Gentoo Linux

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”