[SOLVED] Mirror object about line

Post questions on how to use or achieve an effect in Inkscape.

[SOLVED] Mirror object about line

Postby Grobe » Tue Feb 23, 2010 4:17 am

Hi

This is a feature I rarely have any use for.

I want to draw an simple arrow (to a PNP transistor symbol, so start markers is no god here). This arrow will point right down.
Image

Image above show a quick drawing. I want the angle between the dotted blue line and the sloped line to be exactly the same as the angle between the solid blue line and the sloped line. How can I achieve that?
Last edited by Grobe on Wed Mar 09, 2011 10:12 am, edited 2 times in total.
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: Mirror object about line

Postby brynn » Tue Feb 23, 2010 7:58 am

I'm not sure this is the best way...probably not :P

When you use the Pen tool and after the first click, you'll notice that as you move the pen around the canvas, you can see the angle and length of the segment, should you click at any point. After you do click, that info changes to reflect the new angle and length (distance) of the next segment. So there's only a certain time when you see the info. But I'm thinking you could calculate the angles involved and the angles needed, and accomplish what you want.

Although again, I'm sure there must be a better way :lol:
Basics:
> Help menu > Tutorials
> a Quick Guide to Inkscape
Manual:
> Inkscape: Guide to a Vector Drawing Program
Tutorials:
> Inkscape Community
Development news
> Google+
Gallery:
> Inkscape Community Gallery
User avatar
brynn
 
Posts: 6748
Joined: Wed Sep 26, 2007 4:34 pm
Location: western USA

Re: Mirror object about line

Postby Grobe » Wed Feb 24, 2010 8:14 am

Sure I can always calculate the angle. But then again, it takes long time in order to just draw a single arrow symbol. But yes it's possible I can do it this way.
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: Mirror object about line

Postby syllie » Wed Feb 24, 2010 8:41 am

Why not draw it such that you can use either the horizontal or vertical flip function? Flip it first, assign different stroke, if it makes life easier even add the center line. Group the 2 (or 3) elements, and use that whole symbol in your drawings. (Rotate where needed).

I assume that drawing circuits is not that different from engineering drawings, where you normally have a library set of symbols which are added to a drawing and then moved into place.
By adding the center line you can easily line things up and attach connecting lines to it.

Just my 2 cnts of course.

Cheers,
Syllie
Life is the art of drawing without an eraser. (John W. Gardner)

http://verysimpledesigns.com - graphics resources
http://syllie.com - personal website
User avatar
syllie
 
Posts: 48
Joined: Fri Jan 15, 2010 3:51 pm
Location: Sydney, Australia

Re: Mirror object about line

Postby brynn » Wed Feb 24, 2010 10:18 am

Why not draw it such that you can use either the horizontal or vertical flip function?

Or use a grid with snapping, draw it horizontal or vertical, then rotate? Still, I'm sure there are better ways.
Basics:
> Help menu > Tutorials
> a Quick Guide to Inkscape
Manual:
> Inkscape: Guide to a Vector Drawing Program
Tutorials:
> Inkscape Community
Development news
> Google+
Gallery:
> Inkscape Community Gallery
User avatar
brynn
 
Posts: 6748
Joined: Wed Sep 26, 2007 4:34 pm
Location: western USA

Re: Mirror object about line

Postby Grobe » Sun Oct 24, 2010 9:41 am

I just found the method that works:

However, if somebody have alternative ways, I'll be glad to know ;)
inkscape_012029.png
Sample drawing
inkscape_012029.png (64.2 KiB) Viewed 7818 times

inkscape_012150.png
Draw a help line between the outer point and to the long line center point. Make sure snap to Cusp node and center line is activated.
inkscape_012150.png (60 KiB) Viewed 7818 times

inkscape_012216.png
Group the two short lines and group them together. Then duplicate and vertical mirror.
inkscape_012216.png (64.06 KiB) Viewed 7818 times


It seems I cannot place more than three atachments here :|
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: Mirror object about line

Postby Grobe » Sun Oct 24, 2010 9:47 am

New post neccesary because av limitation on 3 uploaded pictures.

inkscape_012415.png
Move the copy so that the lower end of both help lines (red) touch (snap to) each other. Then click on it another time so it gets rotatable. Move the rotation center to where the help lines touch. It should snap there.
inkscape_012415.png (64.32 KiB) Viewed 7818 times

inkscape_012425.png
Then rotate the object. Place mouse pointer as near the black leg on the duplicated object as possible so that the end of the black duplicated leg snap into the original black leg - the end that touches the long line.
inkscape_012425.png (65.86 KiB) Viewed 7818 times


Last step is to ungroup and remve the red help lines.
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: [Workaround] Mirror object about line

Postby Uktrunie » Sun Oct 24, 2010 12:25 pm

Well, just another idea...

- Draw a rectangle the size you like.
- Move the rotation point towards any corner. (click the shape twice and then drag the little cross).
- Position your shape so the little cross is right over the line.
- Rotate the shape so the opposite corner is in the middle of the line.
- Edit the nodes and delete the node at the corner and delete the segment so you get an arrow shape.

The alignment is not 100% super ultra perfectly exact, but...

Image
Image
Image
Uktrunie
 
Posts: 101
Joined: Sun Jul 18, 2010 4:48 am

Re: [Workaround] Mirror object about line

Postby Grobe » Mon Oct 25, 2010 9:11 am

Uktrunie wrote:The alignment is not 100% super ultra perfectly exact, but...
Yes it can be. If you activate Snap to path and Snap to cusp node :D
I like your idea :)
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: [Workaround] Mirror object about line

Postby Apex » Fri Mar 04, 2011 11:09 am

I found myself needing to do the very same thing this week, I resorted to hacking some python (a first for me), I thought I would share the results!

Pretty simple, to use, duplicate your object, shift-select your axis for reflection and then pick the mirror extension.

mirror.py
Code: Select all
#!/usr/bin/env python
"""
Derived from the "envelope" extension by Aaron Spike, aaron@ekips.org

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""
import inkex, os, simplepath, cubicsuperpath
from ffgeom import *
import gettext
_ = gettext.gettext

try:
    from subprocess import Popen, PIPE
    bsubprocess = True
except:
    bsubprocess = False

class Project(inkex.Effect):
    def __init__(self):
            inkex.Effect.__init__(self)

    def effect(self):
        if len(self.options.ids) < 2:
            inkex.errormsg(_("This extension requires two selected paths. \nThe second path must be exactly two nodes long."))
            exit()

        #obj is selected second
        obj = self.selected[self.options.ids[0]]
        trafo = self.selected[self.options.ids[1]]
        if obj.get(inkex.addNS('type','sodipodi')):
            inkex.errormsg(_("The first selected object is of type '%s'.\nTry using the procedure Path->Object to Path." % obj.get(inkex.addNS('type','sodipodi'))))
            exit()
        if obj.tag == inkex.addNS('path','svg') or obj.tag == inkex.addNS('g','svg'):
            if trafo.tag == inkex.addNS('path','svg'):
                #distil trafo into two node points
                trafo = cubicsuperpath.parsePath(trafo.get('d'))
                if len(trafo[0]) < 2:
                    inkex.errormsg(_("This extension requires that the second selected path be two nodes long."))
                    exit()
                trafo = [[Point(csp[1][0],csp[1][1]) for csp in subs] for subs in trafo][0][:2]

                #START HERE!!!
                self.orig = [trafo[0]['x'], trafo[0]['y']]
                self.vect = vect_dif([trafo[1]['x'], trafo[1]['y']], self.orig)
                self.norm = vect_norm(self.vect)
                self.unit = [self.vect[0]/self.norm, self.vect[1]/self.norm]

                if obj.tag == inkex.addNS("path",'svg'):
                    self.process_path(obj)
                if obj.tag == inkex.addNS("g",'svg'):
                    self.process_group(obj)
            else:
                if trafo.tag == inkex.addNS('g','svg'):
                    inkex.errormsg(_("The second selected object is a group, not a path.\nTry using the procedure Object->Ungroup."))
                else:
                    inkex.errormsg(_("The second selected object is not a path.\nTry using the procedure Path->Object to Path."))
                exit()
        else:
            inkex.errormsg(_("The first selected object is not a path.\nTry using the procedure Path->Object to Path."))
            exit()

    def process_group(self,group):
        for node in group:
            if node.tag == inkex.addNS('path','svg'):
                self.process_path(node)
            if node.tag == inkex.addNS('g','svg'):
                self.process_group(node)

    def process_path(self,path):
        d = path.get('d')
        p = cubicsuperpath.parsePath(d)
        for subs in p:
            for csp in subs:
                csp[0] = self.trafopoint(csp[0])
                csp[1] = self.trafopoint(csp[1])
                csp[2] = self.trafopoint(csp[2])
        path.set('d',cubicsuperpath.formatPath(p))

    def trafopoint(self,(x,y)):
        # x1' = -x1 + 2xo + 2n^[(x1 - xo).n^]
        return vect_sub(vect_add(vect_mul(self.orig, 2), vect_mul(self.unit, 2 * dot_prod(vect_sub([x, y], self.orig), self.unit))), [x, y])

def vect_dif((x1, y1), (x2, y2)):
    return [x2-x1, y2-y1]

def sum_sq((x, y)):
    return x**2 + y**2

def vect_norm((x,y)):
    return sum_sq([x, y])**.5

def vect_add((x1, y1), (x2, y2)):
    return [x1+x2, y1+y2]

def vect_sub((x1, y1), (x2, y2)):
    return [x1-x2, y1-y2]

def vect_mul((x, y), s):
    return [x*s, y*s]

def dot_prod((x1, y1), (x2, y2)):
    return (x1 * x2) + (y1 * y2)

if __name__ == '__main__':
    e = Project()
    e.affect()


# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99


mirror.inx
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
    <_name>Mirror</_name>
    <id>test.apex.mirror</id>
   <dependency type="executable" location="extensions">mirror.py</dependency>
   <dependency type="executable" location="extensions">inkex.py</dependency>
    <effect>
   <object-type>path</object-type>
        <effects-menu>
            <submenu _name="Modify Path"/>
        </effects-menu>
    </effect>
    <script>
        <command reldir="extensions" interpreter="python">mirror.py</command>
    </script>
</inkscape-extension>

I'm sure that python should have most of the vector ops that I cobbled together in its math library, but I didn't take time to look, I'm still a little surprised that I got it to work!

Thanks to Arron Spike for the envelope/prospective extensions that I butchered in order to make this one, and thanks to Wolfram.com for the math!

Happy mirroring!
Apex
 
Posts: 2
Joined: Fri Mar 04, 2011 10:53 am

Re: [Workaround] Mirror object about line

Postby ~suv » Wed Mar 09, 2011 1:40 am

Apex wrote:I found myself needing to do the very same thing this week, I resorted to hacking some python (a first for me), I thought I would share the results!

Pretty simple, to use, duplicate your object, shift-select your axis for reflection and then pick the mirror extension.

Works like a charm - thank you for sharing! Do you think it would be difficult to add support for clones? Might be a handy feature for mirrored drawing… Also, it fails with paths that have a path effect applied - maybe a note to the user to convert the duplicated object to path would be helpful - as is done for text objects (even better though would be to add the transformation in the preserved (explicit) form to the object instead - if doable).

If you happen to build inkscape yourself - you might be interested in checking out the experimental path effects [1] which include 'Mirror symmetry'.

Please consider adding your extension to the list of contributed extensions in the Inkscape Wiki! ;)

[1] it's just one line in one of the source files that needs to be uncommented before building, to enable those.
Code: Select all
=== modified file 'src/live_effects/effect.cpp'
--- src/live_effects/effect.cpp   2011-02-21 07:59:34 +0000
+++ src/live_effects/effect.cpp   2011-02-21 08:13:27 +0000
@@ -5,7 +5,7 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-//#define LPE_ENABLE_TEST_EFFECTS
+#define LPE_ENABLE_TEST_EFFECTS
 
 #include "live_effects/effect.h"
 

~suv
 
Posts: 1955
Joined: Sun May 10, 2009 2:07 am

Re: [Workaround] Mirror object about line

Postby Grobe » Wed Mar 09, 2011 3:42 am

Hi.

Those scripts you're posting here. Is it possible to make new py files in some folder in Inkscape install dir and just run it like that?
If so, where shall I put the files for it to work?

Thanks.
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: [Workaround] Mirror object about line

Postby ~suv » Wed Mar 09, 2011 3:59 am

Grobe wrote: Is it possible to make new py files in some folder in Inkscape install dir and just run it like that?
Yes to both:

Copy the quoted code and paste it into a plain-text editor of your choice (make sure that line indents are preserved), save them as mirror.py and mirror.inx (don't let your OS fool you and add *.txt as hidden file extension).

Grobe wrote:If so, where shall I put the files for it to work?
If you tell us which OS you use, we might be able to help with detailed instructions. ;)

Generic info to install user extensions:
On Linux/Mac OS X put the two files into '~/.config/inkscape/extensions', on Windows into '%APPDATA%\Inkscape\extensions'
~suv
 
Posts: 1955
Joined: Sun May 10, 2009 2:07 am

Re: [Workaround] Mirror object about line

Postby Grobe » Wed Mar 09, 2011 6:44 am

I'm using windows XP.

My prefered text editor is Notepad++.

Testing this now.
I canot "pick the mirror extension", I simply don't know where to look for it. I cannot find it under any menu. I did make the files in correct manner following your description carefully.

Thanks
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: [Workaround] Mirror object about line

Postby ~suv » Wed Mar 09, 2011 7:07 am

Grobe wrote:I cannot find it under any menu.
The extension is listed as 'Extensions > Modify Path > Mirror'

Hint: take a closer look at the *.inx file, it reveals the details:
Apex wrote:
Code: Select all
    <_name>Mirror</_name>
Code: Select all
            <submenu _name="Modify Path"/>
~suv
 
Posts: 1955
Joined: Sun May 10, 2009 2:07 am

Still not working

Postby Grobe » Wed Mar 09, 2011 9:09 am

Hi.

I've put the files to
Code: Select all
C:\Documents and Settings\<Username>\Programdata\inkscape\extensions

(norwegian XP version)

Still, the menu "Extensions > Modify Path > Mirror" isn't to be found there :cry:
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: [Workaround] Mirror object about line

Postby ~suv » Wed Mar 09, 2011 9:37 am

Grobe wrote:Still, the menu "Extensions > Modify Path > Mirror" isn't to be found there :cry:
Does it work with the files from the attached zip archive? (BTW - you did restart Inkscape after placing the files into %APPDATA%\Inkscape\extensions? Inkscape only scans for and loads extensions at launch time)
Attachments
mirror.zip
(2.13 KiB) Downloaded 305 times
~suv
 
Posts: 1955
Joined: Sun May 10, 2009 2:07 am

Re: [Workaround] Mirror object about line

Postby ~suv » Wed Mar 09, 2011 9:46 am

If it still fails to be listed in the menu, can you search in the file 'extension-errors.log' in %APPDATA%\Inkscape if there are any messages about 'Mirror' (like «Extension "Mirror" to load because …»)?

I don't use Windows myself, and it's difficult for me to 'debug' such issues beyond known pitfalls
~suv
 
Posts: 1955
Joined: Sun May 10, 2009 2:07 am

Re: [Workaround] Mirror object about line

Postby Grobe » Wed Mar 09, 2011 10:11 am

Thank you. I just downloaded and extracted the files over the files I created earlier this evening.
Now it works good :D

Also, Apex - thanks very much for the code as it make some of my work more efficient now :D
User avatar
Grobe
 
Posts: 353
Joined: Tue Feb 02, 2010 2:20 am

Re: [SOLVED] Mirror object about line

Postby Apex » Wed Mar 09, 2011 8:32 pm

Grobe:
No problem, glad to hear it is useful!

~suv:
As I said before, most of the code is taken right from the existing perspective/envelope extensions, and so it shares the same limitations on what paths can be modified. I'd never written any Python before last week, and I don't think I've written any "good" python yet ^^ but I'll submit it to the Wiki as suggested anyway. If I feel my Python charming skills (and inkscape internals know-how) improve sufficiently, I will take a stab at implementing the suggested improvements, though I am sure that are experts out there that could do a lot better job than I ^^

A...
Apex
 
Posts: 2
Joined: Fri Mar 04, 2011 10:53 am


Return to Help with using Inkscape

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 4 guests