Applying a transformation to a copy of a sketch, not to the original sketch

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
jcdmelo
Posts: 6
Joined: Mon Jul 15, 2019 8:08 pm

Applying a transformation to a copy of a sketch, not to the original sketch

Post by jcdmelo »

Hi, everyone,

I've got one more question: I am trying to make a vertical mirror of a sketch, and then apply a rotation to the copy. My code read as follows:

Code: Select all

... (stuff)
# Create a base sketch on plane (X,Y)
Sketch1 = CreateSketch1(Vertices)			# No problem

# Create a copy of the base sketch, mirroring it around the X axis
Sketch2 = CopyMoveandRotateSketch (Sketch1, 0.0, 0.0, 0.0, 0.0, 180.0, 'X') # Fine, I get the mirrored sketch (upside down copy)

# Now, I want to rotate Sketch2 around the Z axis
Sketch3 = CopyMoveandRotateSketch (Sketch2, 0.0, 0.0, 0.0, 0.0, Angle, 'Z') # No good!
# TOO BAD! Sketch3 is not a copy of Sketch2 rotated, but a rotated copy of Sketch1!!!
... (stuff)
My copy routine:

Code: Select all

#---------------------------------------------------------------------------
# Copy a sketch with translation and rotation
#---------------------------------------------------------------------------

def CopyMoveandRotateSketch (Sketch, Offx=100.0, Offy=100.0, Cx=0.0, Cy=0.0, Rotation=0.0, Axis='Y'):
   Copy = App.ActiveDocument.copyObject(Sketch, False)
   if Axis == 'X':
      rot = FreeCAD.Rotation(FreeCAD.Vector(1,0,0), Rotation)
   elif Axis == 'Y':
      rot = FreeCAD.Rotation(FreeCAD.Vector(0,1,0), Rotation)
   else:
      rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), Rotation)
   center = FreeCAD.Vector(Cx, Cy, 0.0)
   newplace = FreeCAD.Placement(FreeCAD.Vector(Offx, Offy,0), rot, center)
   Copy.Placement = newplace

   return Copy
My question: how to make Sketch2 an independent copy of Sketch1 and then apply the second rotation to Sketch2, not Sketch1? A picture of what happens is attached.

I read that there was a bug with the copyObject method not returning the new object, but the last one on the stack (https://forum.freecadweb.org/viewtopic. ... 0&p=284274), but I am not sure it relates to the problem I am having.

Thanks,
Julio
Attachments
Picture.png
Picture.png (14.58 KiB) Viewed 754 times
vocx
Veteran
Posts: 5197
Joined: Thu Oct 18, 2018 9:18 pm

Re: Applying a transformation to a copy of a sketch, not to the original sketch

Post by vocx »

jcdmelo wrote: Tue Jan 14, 2020 6:55 pm Hi, everyone,
Important information
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
jcdmelo
Posts: 6
Joined: Mon Jul 15, 2019 8:08 pm

Re: Applying a transformation to a copy of a sketch, not to the original sketch

Post by jcdmelo »

Hi, vocx,

Sorry for omitting information about my FreeCAD installation (I went through the important information, and I hope this was my only fault. Please, let me know of any others.)

Here it is:
OS: Windows 10
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.16117 (Git)
Build type: Release
Branch: releases/FreeCAD-0-18
Hash: dbb4cc6415bac848a294f03b80f65e888d531742
Python version: 3.6.6
Qt version: 5.6.2
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: Portuguese/Brazil (pt_BR)

I also checked for information on copyObject on the Forum, and I did not see any clear answer to my question.

And in case anyone wants to play with the code, here it is:

Code: Select all

import FreeCAD, FreeCADGui, Part, Sketcher, math
App = FreeCAD
Gui = FreeCADGui

FreeCAD.newDocument("MirrorTest")

#---------------------------------------------------------------------------
# Set sketch vertices
#---------------------------------------------------------------------------

def SetVertices ():

   v1 = FreeCAD.Vector(-30, -100.0, 0.0)
   v2 = FreeCAD.Vector(40, -70.0, 0.0)
   v3 = FreeCAD.Vector(0, 80.0, 0.0)
   v4 = FreeCAD.Vector(-60, -70.0, 0.0)
   Vertices = ([v1,v2,v3,v4])

   return Vertices

#---------------------------------------------------------------------------
# Create original sketch
#---------------------------------------------------------------------------

def DefineSketch (Sketch, Vertices):

      Sketch.addGeometry(Part.LineSegment(Vertices[0],Vertices[1]))
      Sketch.addGeometry(Part.LineSegment(Vertices[1],Vertices[2]))
      Sketch.addConstraint(Sketcher.Constraint('Coincident',0,2,1,1)) 
      Sketch.addGeometry(Part.LineSegment(Vertices[2],Vertices[3]))
      Sketch.addConstraint(Sketcher.Constraint('Coincident',1,2,2,1)) 
      Sketch.addGeometry(Part.LineSegment(Vertices[3],Vertices[0]))
      Sketch.addConstraint(Sketcher.Constraint('Coincident',2,2,3,1)) 
      Sketch.addConstraint(Sketcher.Constraint('Coincident',3,2,0,1)) 

#---------------------------------------------------------------------------
# Copy a sketch with translation and rotation
#---------------------------------------------------------------------------

def CopyMoveandRotateSketch (Sketch, Offx=100.0, Offy=100.0, Cx=0.0, Cy=0.0, Rotation=0.0, Axis='Y'):
   Copy = App.ActiveDocument.copyObject(Sketch, False)
   if Axis == 'X':
      rot = FreeCAD.Rotation(FreeCAD.Vector(1,0,0), Rotation)
   elif Axis == 'Y':
      rot = FreeCAD.Rotation(FreeCAD.Vector(0,1,0), Rotation)
   else:
      rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), Rotation)
   center = FreeCAD.Vector(Cx, Cy, 0.0)
   newplace = FreeCAD.Placement(FreeCAD.Vector(Offx, Offy,0), rot, center)
   Copy.Placement = newplace

   return Copy

def CreateSketch (V):
   Sketch=FreeCAD.ActiveDocument.addObject('Sketcher::SketchObject','Sketch')
   DefineSketch (Sketch, V)
   App.ActiveDocument.recompute()
   return Sketch

#---------------------------------------------------------------------------
# Main program
#---------------------------------------------------------------------------

VHB = SetVertices()
Sketch1 = CreateSketch(VHB)
Sketch2 = CopyMoveandRotateSketch (Sketch1, 0.0, 200.0, 0.0, 0.0, 180.0, 'X')
Sketch3 = CopyMoveandRotateSketch (Sketch2, 0.0, 0.0, 0.0, 0.0, -45.0, 'Z')

Sketch1.Label='Sketch1'
Sketch2.Label='Sketch2'
Sketch3.Label='Sketch3'

App.ActiveDocument.recompute()
Gui.SendMsgToActiveView("ViewFit")
Gui.activeDocument().activeView().viewTop()
As I said, I was expecting Sketch3 to be a rotated copy of Sketch2, not of Sketch1.

Thanks,
Julio
vocx
Veteran
Posts: 5197
Joined: Thu Oct 18, 2018 9:18 pm

Re: Applying a transformation to a copy of a sketch, not to the original sketch

Post by vocx »

jcdmelo wrote: Wed Jan 15, 2020 4:55 pm ...
And in case anyone wants to play with the code, here it is:
What you should do is draw by hand the shapes that you want to obtain. Right now you are saying that you are obtaining wrong shapes. But what do you actually expect?

Maybe you aren't understanding how Placement works.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
jcdmelo
Posts: 6
Joined: Mon Jul 15, 2019 8:08 pm

Re: Applying a transformation to a copy of a sketch, not to the original sketch

Post by jcdmelo »

Hi, vocx,

Thanks for your hint, but I think you did not understand my question. I read through the Placement docs, and I think the problem is not related to it, but rather to copying objects.

As you can see in the code sent before, what I want is to apply a transformation to a copy (Sketch2) of a base sketch (Sketch1), by using Sketch2 as the argument of a second call to my copying routine. Instead, what I get is a transformed copy of Sketch1. As a matter of fact, in the second call, it works the same if I change the argument to Sketch1, further confirming that it is indeed the sketch that is being passed to the routine. "Picture1" shows what I am getting and "Picture corrected" below shows what I am expecting to accomplish.

To further confirm my belief that this is a copying problem, I went ahead and did as you suggested: I drew by hand the figures shown, starting from Sketch1, copying it to Sketch2, after which I applied a rotation of 180 degrees around the X-axis, copying it to Sketch3 and then applying a rotation of 10 degrees around the Z-axis to obtain what I wanted. All I want is to be able to do this with the Python script I sent.

Thanks,
Julio
Attachments
Picture1.png
Picture1.png (113.07 KiB) Viewed 650 times
Picture corrected.png
Picture corrected.png (116.85 KiB) Viewed 650 times
vocx
Veteran
Posts: 5197
Joined: Thu Oct 18, 2018 9:18 pm

Re: Applying a transformation to a copy of a sketch, not to the original sketch

Post by vocx »

jcdmelo wrote: Sun Jan 19, 2020 8:13 pm Hi, vocx,

Thanks for your hint, but I think you did not understand my question....
Yes, and I think you didn't explain it properly.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
User avatar
Chris_G
Veteran
Posts: 2601
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Applying a transformation to a copy of a sketch, not to the original sketch

Post by Chris_G »

In your CopyMoveandRotateSketch function, you do this :

Code: Select all

Copy.Placement = newplace
It means that you are replacing Copy's placement by a new one

Code: Select all

Sketch2 = CopyMoveandRotateSketch (Sketch1, 0.0, 0.0, 0.0, 0.0, 180.0, 'X')
Sketch2.Placement
# returns : Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,180)]
Sketch3 = CopyMoveandRotateSketch (Sketch2, 0.0, 0.0, 0.0, 0.0, 45, 'Z')
Sketch3.Placement
# returns : Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(45,0,0)]
But you want your function to have a cumulative effect, so, in your CopyMoveandRotateSketch function, the placement should be :

Code: Select all

Copy.Placement.Matrix = Sketch.Placement.Matrix.multiply(newplace.Matrix)
jcdmelo
Posts: 6
Joined: Mon Jul 15, 2019 8:08 pm

Re: Applying a transformation to a copy of a sketch, not to the original sketch

Post by jcdmelo »

Thanks, Chris and vocx,

That solved my question. I don't know if it is a version issue or just a different syntax, but the actual statement is slightly different from what you suggested. I have yet to grasp a lot of FreeCAD concepts, and Python, and OOP, ...

I used:

Code: Select all

   Copy.Placement = Sketch.Placement.multiply(newplace)
instead of:

Code: Select all

   Copy.Placement.Matrix = Sketch.Placement.Matrix.multiply(newplace.Matrix)
Julio
Post Reply