IDML : How are shapes stored in IDML files? - geometry

I have encountered multiple shapes while reading IDML spreads. Each Shape has it's own geometry that looks like -
-<PathGeometry>
-<GeometryPathType PathOpen="false">
-<PathPointArray>
<PathPointType RightDirection="-611.5 1548.5" LeftDirection="-611.5 1548.5" Anchor="-611.5 1548.5"/>
<PathPointType RightDirection="-611.5 2339.5" LeftDirection="-611.5 2339.5" Anchor="-611.5 2339.5"/>
<PathPointType RightDirection="-533.3 2339.5" LeftDirection="-533.3 2339.5" Anchor="-533.3 2339.5"/>
<PathPointType RightDirection="-533.3 1548.5" LeftDirection="-533.3 1548.5" Anchor="-533.3 1548.5"/>
</PathPointArray>
</GeometryPathType>
</PathGeometry>
For rectangles it is trivial (as in the example above), where each attribute in a <PathPoint> element points to an end point in the rectangle. What happens with other shapes? In other words, what do RightDirection, LeftDirection and Anchor attributes signify? Is there a way to determine what shape it is looking at the PathPointArray?
Thanks.

Each IDML PathPointType is a node on a cubic bezier curve. The combination of control and anchor points defines the end points and curvature of the line. All lines in IDML are defined as if they were curves but, as you have noticed, the control and anchor points for a straight line are identical. Straight line polygons (such as a triangle) are defined the same way.
IDML has only a small collection of shape types (rectangles, ellipses, graphic lines, polygons - see 10.3.1. in the specification). You can draw any shape from IDML simply by drawing it one line at a time, but it's more efficient to create separate routines for rectangles and ellipses.
Note also PathOpen="false" on the GeometryPathType element. For efficiency, the last line in a shape isn't defined - you will create a line from the final point back to the first if PathOpen == false.

Related

Finding the filled side of an SVG path

I am creating an animation the camera moves along the path from M to z (closed path). As the camera moves, I need to know which side is inside the closed path.
Since the inside of a path is formed by clockwise move (in the default fill-rule of nonzero), I assumed the inside is always on the right side of the path.
However, I encountered cases where the filled area is on the left side of the path.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26.986 26.986"><path d="M.614 2.145V24.84C.614 26.028 1.575 26.986 2.759 26.986H24.226C25.41 26.986 26.372 26.027 26.372 24.84V2.145C26.372 .963 25.409 0 24.225 0H2.759C1.575 0 .614 .963 .614 2.145zM8.778 20.82C8.778 22.353 7.534 23.599 6.001 23.599C4.466 23.599 3.224 22.353 3.224 20.82C3.224 19.289 4.466 18.043 6.001 18.043C7.534 18.043 8.778 19.289 8.778 20.82zM23.696 5.596C23.696 7.131 22.45 8.375 20.917 8.375C19.386 8.375 18.142 7.131 18.142 5.596C18.142 4.063 19.386 2.819 20.917 2.819C22.45 2.818 23.696 4.062 23.696 5.596z"/>
<circle cx="0.614" cy="2.145" r="2" fill="red"/>
<path d="M.614 2.145V24.84" stroke="blue" />
</svg>
I know we can check if a typical point is inside the closed path by polygon methods.
I wonder if there is a simpler method for finding the inside of a closed path when moving from M to z?
I just need to know when moving from M to z, the inside of the closed path is on the right or left side of the camera.
The first assumption
...the inside of a path is formed by clockwise move...
is only true if the path is non-overlapping and does not define a hole. If your path never crosses itself and has no holes, the inside will always be to your right assuming that you are following the path in a clockwise move. However, in your example the movement from the red dot through the blue line is counterclockwise.
A general solution to this problem would be long and laborious. However, depending on the design of your script, it might be much simpler. If you are always drawing your figure clockwise (as in your example), the inside is to your rigth when you follow the same order of points, and to your left if you are reversing the order of your points. Notice that in your example you are reversing the order of points - the path is closed from the last point (z) to the first (M).
If not, this procedure should work:
Start with the point where the camera is and the vector showing where it points.
Rotate this vector by any angle higher than 0 and lower than π (that would be to the left).
Follow the vector from the point of the camera and find how many times it intersects with your path (current segment excluded). If this number is even, the inside is to the right of the camera. If the number is odd, it is to the left.
This is feasible, but by no means trivial. For the third step, you might use the bounding box of your path as "infinity". To exclude the current segment, your procedure to find the intersection of two segments should return false if one of the extremes of one segment belongs to the other segment. It should also return false if both segments are parallel. You would also need to decide the behavior you want in special points, such as vertices.

.translated function not working in Godot / best way to change position of bone

I'm working on a program in Godot using Gdscript, and I ran into a problem when trying to use the Transform.translated(Vector3) function. My code is supposed to move a bone to (0,0,0) by translating it by its current coordinates but with negative sign. Example: (1,2,3) would be translated by (-1,-2,-3) so it would end up at (0,0,0). For some reason when I do this, the end position of the bone is not (0,0,0), but some other coordinate. In the Godot documents, it says the .translated function is "relative to the transform's basis vectors", so maybe that's why? Also if there is a better way to change a bones position than using the Transform.translated(Vector3) function that would be helpful too. Thanks!
My Code:
bonePose = skel.get_bone_global_pose(bone)
var globalBonePose = skel.to_global(bonePose.origin)
translateVector = -globalBonePose
var newPose = bonePose.translated(translateVector)
skel.set_bone_pose(bone, newPose)
Code Output / Results:
bonePose (the original position of the bone) is around (-0.82,0.49,0.50)
translateVector (the amount the bone will be translated) is around (0.82,-0.49,-0.50)
newPose (the final position of the bone -- should be [0,0,0]) is around (0.82,-0.66,-0.46). Even when I call skel.to_global(newPose.origin) to see the global coordinates, it's (-0.76,0.44,0.42), which is not (0,0,0)
In Godot a Transform is composed of a basis (a Basis) and an origin (a Vector3). Where the origin handles the translation part of the transform, and the Basis the rest.
A Basis is the set of vectors that define the coordinate system. There is a vector that defines the x axis, another for the y axis, and another for the z axis. And this is the way Godot will encode rotation and scaling transformations.
When the documentation says "relative to the transform's basis vectors" it means the Basis will be applied to the vector you pass in. Thus, in your case, you are getting a translation on the local space of the bone. Which implies that if the bone is rotated or scaled (or something like that), that will affect the translation.
If you don't want to deal with rotation, scaling, et.al. I suggest you work with the origin of the Transform instead.
If you have a Transform and you want another that is otherwise equal but located at (0, 0, 0), you do this:
var new_transform = Transform(transform.basis, Vector.ZERO)
Or replace Vector.ZERO with whatever origin you want to give the new transform.
I also need to remind you that get_bone_global_pose and set_bone_pose do not operate on the same thing. On one hand set_bone_pose is relative to the parent bone, on the other get_bone_global_pose is relative to the Skeleton. Thus, I suggest you use set_bone_global_pose_override instead.
The final piece you need is the opposite of Spatial.to_global. Because setting the pose like as follows…
bonePose = skel.get_bone_global_pose(bone)
var newPose = Transform(bonePose.basis, Vector.ZERO)
skel.set_bone_global_pose_override(bone, newPose, 1.0)
… Would place it at the origin of the Skeleton.
Well, the opposite of Spatial.to_global is Spatial.to_local, and you would use it like this:
bonePose = skel.get_bone_global_pose(bone)
var newPose = Transform(bonePose.basis, skel.to_local(Vector.ZERO))
skel.set_bone_global_pose_override(bone, newPose, 1.0)
Here skel.to_local(Vector.ZERO) should give the origin of the world relative to the Skeleton. And given that set_bone_global_pose_override wants a Transform relative to the Skeleton, the result should be that the bone is placed at the origin of the world. With its rotation and scaling preserved.

PyQt: Obtain all pixels inside QPolygon

In PyQt 5, is there a way to obtain all pixel positions that would be modified by a call to QPainter.drawPolygon for a QPainter object constructed with some QImage as an argument without actually drawing the polygon? Ideally I would like to obtain separate sets of pixel positions for the polygon's border and for all pixels inside the polygon.
Just like #ekhumoro said, QPolygon is a subclass of QVector (that is, a QList). However, in Pyqt this is a Python array and not a QList. I got runtime errors when trying to iterate over this list, because it was inside the QPolygon object and there was no getter. In this case, in PyQt the solution is not very efficient. You need to iterate over each pixel of the image, creating a QPoint with pixel coordinates and checking if the QPolygon contains this point through the containsPoint method. There aren't many implementation details, but consider the following code snippet.
array_qpoints = [] # this array will have all the QPoints
polygon = QPolygon([
QPoint(140,234),
QPoint(126,362),
QPoint(282,409),
QPoint(307,273),
QPoint(307,233),
])
# let's consider a 640x480 image
for x in range(640):
for y in range(480):
point = QPoint(x, y)
if polygon.containsPoint(point, Qt.FillRule.OddEvenFill):
array_qpoints.append(point)
You can get the coordinates of each pixel by calling the x() and y() methods for each element in array_qpoints.
for point in array_qpoints:
x = point.x()
y = point.y()
# do what you want with the information
I'm posting this answer for others who visit this question and are looking for a solution by code. Since it's been several years, if you've found a better solution, please post :)

What do the 'M', 'c' and 'z' mean in SVG paths?

http://paperjs.org/examples/
I'm trying to create a custom path with Chain, and I see that Tadpoles has a predefined heart-shaped path, so I'm trying to copy it but I don't understand a few parts of it.
var heartPath = new Path('M514.69629,624.70313c-7.10205,-27.02441 -17.2373,-52.39453 -30.40576,-76.10059c-13.17383,-23.70703 -38.65137,-60.52246 -76.44434,-110.45801c-27.71631,-36.64355 -44.78174,-59.89355 -51.19189,-69.74414c-10.5376,-16.02979 -18.15527,-30.74951 -22.84717,-44.14893c-4.69727,-13.39893 -7.04297,-26.97021 -7.04297,-40.71289c0,-25.42432 8.47119,-46.72559 25.42383,-63.90381c16.94775,-17.17871 37.90527,-25.76758 62.87354,-25.76758c25.19287,0 47.06885,8.93262 65.62158,26.79834c13.96826,13.28662 25.30615,33.10059 34.01318,59.4375c7.55859,-25.88037 18.20898,-45.57666 31.95215,-59.09424c19.00879,-18.32178 40.99707,-27.48535 65.96484,-27.48535c24.7373,0 45.69531,8.53564 62.87305,25.5957c17.17871,17.06592 25.76855,37.39551 25.76855,60.98389c0,20.61377 -5.04102,42.08691 -15.11719,64.41895c-10.08203,22.33203 -29.54687,51.59521 -58.40723,87.78271c-37.56738,47.41211 -64.93457,86.35352 -82.11328,116.8125c-13.51758,24.0498 -23.82422,49.24902 -30.9209,75.58594z');
I don't understand what the M at the start of the path means, or the c in some of the values or z at the end of the path. I tried to find info about it in their docs or Google it but I can't find what I want because single letters make searching tough.
I tried to remove the M at the start and the Tadpoles stopped moving, so I assume M potentially means 'moving'? Removing the c alters the shape of the heart, but removing the z doesn't seem to change anything.
M: Move to
The command "Move To" or M, which was described above. It takes two parameters, a coordinate ' x ' and coordinate ' y ' to move to. If your cursor already was somewhere on the page, no line is drawn to connect the two places. The "Move To" command appears at the beginning of paths to specify where the drawing should start
z: Close Path
This command draws a straight line from the current position back to the first point of the path. It is often placed at the end of a path node, although not always. There is no difference between the uppercase and lowercase command.
c: Bezier Curves
The cubic curve, C, is the slightly more complex curve. Cubic Beziers take in two control points for each point. Therefore, to create a cubic Bezier, you need to specify three sets of coordinates.
source: https://developer.mozilla.org/en/docs/Web/SVG/Tutorial/Paths
-EDIT-
You can visit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d for a full reference to all the possible commands and their usage.
The constructor you are invoking is this:
Path(, pathData)
Where pathData is described as:
the SVG path-data that describes the geometry of this path
The documentation you should read is the one of SVG.
As #GerardoFurtado mentioned in the comments, here is a read that could be of interest for you.

Point of collision between Shapes

I have a problem in with colissions in JavaFX.
First, I detect a collision between a line and a circle using the follow code:
if(line.getBoundsInParent().intersects(circle.getBoundsInParent())){
System.out.println("Collision!");
}
After this, I need catch the coordinate of collision, like the below figure:
How can I catch this coordinate?
Since Line and Circle are both Shapes, you can use the static method intersect in Shape to find their intersection:
Shape collisionArea = Shape.intersect(line, circle)
That collisionArea is a Node as well, so you can use its boundsInParent to find out where to collision took place. Or you could use localToScene or localToScreen to transform local coordinates to scene or screen coordinates if you prefer those.

Resources