92

This answer evolved over time and got quite long in the process. I've created a cleaned-up, restructured version as an answer to a very similar question on dsp.stackexchange. Here's my quick&dirty solution. It's a bit similar to @azdahak's answer, but it uses an approximate mapping instead of cylindrical coordinates. On the other hand, there are no ...


29

lin[cam_, obj_][t_] := cam t + (1 - t) obj s[cam_, obj_] := First@Solve[lin[cam, obj][t][[3]] == 0, t]; tr[cam_, obj_] := lin[cam, obj][t] /. s[cam, obj] // FullSimplify And that's it: tr[ ] is your transformation function. Let's test it with a Rubik's cube, simulating the video you linked. The following boring part is building the cube. We will make only ...


23

The idea is quite simple: Since any great circle can be parametrized as $\cos(\theta)u + \sin(\theta)v$ where $u$ and $v$ are two orthonormal vectors. One can start with $u=\{1,0,0\}, v=\{0,1,0\}$ and use RotationTransform to get out of the xy plane, then use RotationTransform again to spin around the z-axis to get all great circles with desired inclination. ...


21

This is just a quick sketching out of an answer (rescales galore!) textOnCurve[text_, f_, n_, p_: 0.01] := Text[Rotate[text, ArcTan @@ (f[Rescale[n + p, {0, 1}, {p, 1 - p}]] - f[Rescale[n - p, {0, 1}, {p, 1 - p}]])], f[n]] textCurve[string_, f_, stylef_: (# &), range_: {0, 1}] := With[{chars = Characters@...


21

A few minor mistakes: corners and the target coordinates weren't in the same order For some reasons, pixels isn't the default unit for ImagePerspectiveTransformation and friends - you have to specify PlotRange and DataRange explicitly the target coordinates should go first in FindGeometricTransform - alternatively, you can pass InverseFunction@ft[[2]] to ...


18

Here's another way...Text[] has a direction argument, so ArcTan is not necessary. txt1 = "Now we can follow" // Characters; txt2 = "an arbitrary path" // Characters; f[t_] := {Cos[2 π t], Sin[6 π t]}; totalarclength = NIntegrate[Sqrt[f'[τ].f'[τ]], {τ, 0, 1}]; invarclength = First@NDSolve[{D[$t[s], s] == 1/Sqrt[f'[$t[s]].f'[$t[s]]], $t[0] == 0}, $t, {s, 0, ...


18

Doing this with basic image processing can be done. In comparison to the post you have linked, your situation is more complicated because you have a monochrome image with no option to separate colors. Additionally, your graph is surrounded by a frame. Let's assume we want to separate not the line but the area under or over the line that is inside the frame. ...


17

Here is a static solution to the problem. It shows a mesh on the sphere that represents the normal lat-long coordinate system. A function representing the equator. equator[θ_] := {Cos[θ], Sin[θ], 0} A function and a plot representing the inclined circle. Note that the inclination is accomplished by a rotation of the equator about the x-axis. ...


16

Here's a simple method that seems to work. Call the grid above img. Find the best/strongest line in the image: lines = ImageLines[img, MaxFeatures -> 1] We'll need the slope of this line - here's a function to do that slope[s_, e_] := ArcTan@@(e - s); (shorter version thanks to nikie). This can be applied as slopeLine = First[slope @@@ lines] For ...


16

You're very close: First, ImageTransformation by default assumes that the range of the coordinate system for the input image is [...] {{0,1},{0,a}}, where a is the aspect ratio If you want to work with pixel coordinates, you have to add PlotRange->Full. Second, the transformation passed to ImageTransformation should transform coordinates from the ...


15

Here's my stab at it, using a cylindrical projection, and TextureCoordinateFunction with a fitting parameter. Replace IMG in the code with the actual photo. The last command is a manual crop. result=With[{para = 1.69}, ParametricPlot3D[{Cos[u], Sin[u], v}, {u, 0, Pi}, {v, 0, Pi}, PlotStyle -> Texture[ImageReflect[IMG, Left -> Right]], Mesh -> ...


14

Great answers have already appeared. In the spirit of demonstrating multiple solutions to a problem with Mathematica, I would like to offer one using a different approach. First, some geometric analysis. This great circle bounds a hemisphere lying in a half-space determined by a normal direction to the circle's plane. Letting $\theta$ be the latitude at ...


14

Using Composition I can apply RotationTransform, TranslationTransform , ShearingTransform one after the other. Graphics3D[{ Opacity[1] , Red , Arrow[{{0, 0, 0}, {1, 0, 0}}] , Green , Arrow[{{0, 0, 0}, {0, 1, 0}}] , Blue , Arrow[{{0, 0, 0}, {0, 0, 1}}] , Opacity[0.2] , GeometricTransformation[Cuboid[-{1, 1, 1}/4, {1, 1, 1}/4], ...


13

Rotation about the origin MapIndexed[N@Nest[r, #1, First[#2-1]] &, points] {{0., 0., 0.}, {0.984808, 0.173648, 0.}, {1.87939, 0.68404, 0.}, {2.59808, 1.5, 0.}, {3.06418, 2.57115, 0.}, {3.21394, 3.83022, 0.}} ListPlot[%[[All, {1, 2}]]] the norm of the vectors is conserved. Rotation about the last point Ok, with the new request, rotating with ...


13

EulerMatrix is available in MMA 10. To obtain the matrix for the transformation shown in your sketch, apply EulerMatrix[{α,β,γ},{3,1,3}] This transformation is known as the x-convention, because the second rotation is about x'-axis. The Wikipedia designates this by ZXZ. Those who do not have MMA 10 can obtain the same x-convention transformation using ...


12

If you have v9, here's an alternative solution: first I calculate the gradient and gradient orientation for each pixel gray = ColorConvert[img, "Grayscale"]; orientation = GradientOrientationFilter[gray, 3]; gradient = GradientFilter[gray, 3]; then I create a weighted histogram from those: wd = WeightedData[Flatten[ImageData[orientation]], Flatten[...


12

I think the "ugly thing" might be because texture is interpolated on triangles (demonstrated after), and a quadrangle is only divided into 2 triangles - up-left and down-right. So to solve the problem, we just need a triangulation network with much higher resolution. One way is to use ParametricPlot: ParametricPlot[ Evaluate[tr@{u, v}], {u, 0,...


12

Here's a nice one-liner: TransformationFunction[{{1, 0, 0, 0}, {0, 0, -1, 0}, {0, 1, 0, 3}, {0, 0, 0, 1}}] // InverseFunction TransformationFunction[{{1, 0, 0, 0}, {0, 0, 1, -3}, {0, -1, 0, 0}, {0, 0, 0, 1}}] Note that TransformationFunction[] is the head of the results returned by geometric *Transform functions, which take a homogeneous transformation ...


12

I wouldn't try to do this on a square (assuming you want at least some sort of systematic correspondence between edges on the sphere and their projections), at least if you don't want crossings on square sides. As @Szabolcs stated, you can't really do this without extreme distortion. You may use map projections, though, picking your poison (for the mesh ...


11

Just use MeshFunction. Manipulate[ParametricPlot3D[{Sin[\[Theta]] Cos[\[Phi]], Sin[\[Theta]] Sin[\[Phi]], Cos[\[Theta]]}, {\[Theta], 0, \[Pi]}, {\[Phi], 0, 2 \[Pi]}, PlotStyle -> Opacity[0.5], Mesh -> {{0.}}, MeshStyle -> {Red, Thick}, MeshFunctions -> {Sin[a] Cos[b] #1 + Sin[a] Sin[b] #2 + Cos[a] #3 &}], {a, 0, \[Pi]}, {b, 0, 2 \[Pi]}] Let ...


11

try: f = FindGeometricTransform[pointSetNoise, pointSetPerfect, "Transformation" -> "Rigid", Method -> "FindFit"] I know it's too short for an answer, but that's it. The result can be tested like this: ListPlot[{f[[2]][pointSetPerfect], pointSetNoise}, Axes -> False, Frame -> True]


11

If you have a homogenous transformation matrix of the form $$\begin{bmatrix} \mathrm{R_{3 \times 3}} & \mathrm{d}_{3 \times 1} \\ 0_{1\times 3} & 1_{1\times 1} \end{bmatrix}$$ Then the inverse is given by $$\begin{bmatrix} \mathrm{R}^{-1} & -\mathrm{R}^{-1}\mathrm{d} \\ 0 & 1 \end{bmatrix}$$ Therefore, if your ...


10

A bug report has been generated on this issue, but I don't believe any resources are being expended on it at the present time (note that the more user reports are received on an issue, the more likely it is that the issue will get resources). As a workaround, it is possible to hook into the internal code that is used for Graphics3D primitives. The key idea ...


10

@nikie gave a very nice answer. This is a complement to it. One remaining challenge is compensating for the distortion close to the left and right edges of the image, visible for example here (image taken from nikie's post): The magnitude of the distortion cannot be estimated in the general case without having some information about what's on the label. ...


10

RotationTransform[a Pi, {1, 0, 0}] is nothing more than a matrix, so you can compose/combine such functions using matrix multiplication. For example: Graphics3D[{EdgeForm[None], GeometricTransformation[Cylinder[], RotationTransform[.5 Pi, {1, 0, 0}].RotationTransform[0.2 Pi, {0, 1, 0}].RotationTransform[0.1 Pi, {0, 1, 0}]]}] In the above code ...


10

Here is the general answer for any shaped object of surface genus-0, though it can have holes as long as it's an outer boundary (maybe its more general and someone can correct me). I will first describe the general UV mapping. This is usually done for a surface with a pre-chosen boundary, you need to choose which points are part of the boundary and give ...


9

Use Composition: Manipulate[Graphics3D[{EdgeForm[None], GeometricTransformation[Cylinder[], Composition[ RotationTransform[a Pi, {1, 0, 0}], RotationTransform[b Pi, {0, 1, 0}], RotationTransform[c Pi, {0, 1, 0}]]]}], {{a, 0}, -1, 1}, {{b, 0}, -1, 1}, {{c, 0}, -1, 1}, SaveDefinitions -> True] (I'm not sure which order you want, ...


9

To address your actual problem: If you're just looking to re-orient your B-spline cylinder, there's no need to go through the Euler angles. Here's one way. Consider the following cylinder: myCyl = BSplineSurface[{{{0, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0}}, {{0, 0, 1}, {0, 1, 1}, {1, 1, 1}, {1, 0, 1}}}, ...


9

You are looking for TransformedRegion. GeometricTransformation is for transforming graphics primitives, but you are looking at region functionality. This is a case where the difference is important. Simply, t = TransformedRegion[p, AffineTransform@A] (* Parallelogram[{0, 0}, {{-1, 2}, {3, 0}}] *) where the AffineTransform was needed as TransformedRegion ...


Only top voted, non community-wiki answers of a minimum length are eligible