4
$\begingroup$

I have a basic question but i cant seem to find an answer for it.

How do i draw a rectangle in mathematica with either clockwise or counterclockwise arrow heads. enter image description here

In this picture i know two points i.e. (xmin,ymin) and (xmax,ymax). I want to stepwise quench my system and show it in this picture and hence many rectangles between min and max.

Rectangle command doesnt seem to provide an answer. And i want to do it with very many points, hence couple of answers that are available in forum are not so useful.

(-1+X+1/(1/3+(-3.+3 X)/(3 (1.*10^-18+4.5*10^-12 (2+X)+2.59808*10^-9 Sqrt[4.*10^-12-4 (-1+X)^3+1.*10^-6 (8-(-20+X) X)])^(1/3))+333333. (1.*10^-18+4.5*10^-12 (2+X)+2.59808*10^-9 Sqrt[4.*10^-12-4 (-1+X)^3+1.*10^-6 (8-(-20+X) X)])^(1/3)))/X

This is the plotted function f.

Now i want to select two X values say X=1.1 and X=3 and divide interval into N parts X = {X1, X2, X3, X4, X5} and directed rectangle between each of the two consecutive values.

Because i cant do it in mathematica i drew it in paint and it looks something like this with clockwise arrows for each rectangle.

enter image description here

Thanks, Nitin

$\endgroup$

3 Answers 3

6
$\begingroup$

Because using Graph is fun:

f[x_] := Sqrt@x
x = {1.1, 1.6, 2.2, 2.4, 3}; (* put any thing you want here *)
coord = {First@#, {First@#[[2]], Last@#[[1]]}, Last@#, {First@#[[1]], Last@#[[2]]}} & /@
         Partition[{#, f@#} & /@ x, 2, 1];
ef1[el_, ___] := {[email protected], Arrow[el]}
g = Graph[{1 -> 2, 2 -> 3, 3 -> 4, 4 -> 1}, 
          VertexCoordinates -> #, 
          EdgeShapeFunction -> ef1] & /@ coord;
Show[Plot[f[x], {x, 0, 5}, Frame -> True], g]

enter image description here

Then you can play with EdgeStyle or VertexStyle in g to have fancy colors (or see Graph's Options for more details) and with Arrowheads to have bigger/smaller heads.


Additions regarding coord (as requested in the comments):

If you consider that {{x1,y1},{x2,y2},{x3,y3}} are the coordinates of the three first points crossing f@x you need to group them in order to create two rectangles:

rectgroups = Partition[{{x1,y1},{x2,y2},{x3,y3}}, 2, 1]

{{{x1, y1}, {x2, y2}}, {{x2, y2}, {x3, y3}}}

with {{x1, y1}, {x2, y2}} and {{x2, y2}, {x3, y3}} forming two rectangles by their opposed coordinates.

The problem here is that in order to draw a rectangle while using VertexCoordinates (it's in fact not the case with Rectangle) you need the four points defining your rectangle. Thus:

makerect = {First@#, {First@#[[2]], Last@#[[1]]}, Last@#, {First@#[[1]], Last@#[[2]]}}&;
makerect /@ rectgroups

{{{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}}, {{x2, y2}, {x3, y2}, {x3, y3}, {x2, y3}}}

gives you the two other coordinates needed to define the rectangles ({x2,y1} and {x1,y2} in the first case).

$\endgroup$
1
  • $\begingroup$ Awesome, thanks a lot. If possible can you please explain how you defined coord, i mean the logic and meaning of the way u defined it. $\endgroup$
    – nitin
    Mar 10, 2014 at 21:44
7
$\begingroup$

Arrow works for this, because the option Arrowheads can be specified to create arrowheads in the way that you want. rm -rf helped write the code (see comment), and it goes like this:

arrowRectangle[s_, {{xmin_, ymin_}, {xmax_, ymax_}}] := With[
  {a = Abs[xmax - xmin], b = Abs[ymax - ymin]}, {
   Arrowheads[Thread[{s, 0.5 {a/2, a + b/2, 3 a/2 + b, 2 a + 3 b/2}/(a + b)}]], 
   Arrow@{{xmin, ymin}, {xmax, ymin}, {xmax, ymax}, {xmin, ymax}, {xmin, ymin}}
   }]
f[x_] := x^2
pts[lower_, upper_, n_] := Partition[{#, f[#]} & /@ Range[lower, upper, (upper - lower)/n], 2, 1]
Show[Plot[f[x], {x, 0, 5}], Graphics[{arrowRectangle[0.04, #] & /@ pts[1, 5, 3]}]]

arrowheads

0.04 is the arrowhead size and might need to be adapted depending on the plot. The formula inside Arrowheads determines each midpoint. This is because the second argument of Arrowheads, the position, goes from 0 to 1 during the length of the entire line. The denominator is the length of the entire line, and each element in the list the distance from the beginning of the line to each midpoint.

$\endgroup$
6
  • $\begingroup$ thanks but this approach will be really tedious if i have many points. $\endgroup$
    – nitin
    Mar 10, 2014 at 15:25
  • $\begingroup$ @nitin I don't see why. Just Arrow[coords[Sequence@@#]]&/@points should work. If you elaborate your question with sample points I might be able to help. $\endgroup$
    – C. E.
    Mar 10, 2014 at 15:29
  • $\begingroup$ @Pickett I have edited question. $\endgroup$
    – nitin
    Mar 10, 2014 at 15:41
  • $\begingroup$ @Pickett The positioning of the arrowhead is off because you need to pick the midpoints of each side. Perhaps this would be better: arrowRectangle[s_, {{xmin_, ymin_}, {xmax_, ymax_}}] := With[{a = Abs[xmax - xmin], b = Abs[ymax - ymin]}, {Arrowheads[Thread[{s, 0.5 {a/2, a + b/2, 3 a/2 + b, 2 a + 3 b/2}/(a + b)}]], Arrow@{{xmin, ymin}, {xmax, ymin}, {xmax, ymax}, {xmin, ymax}, {xmin, ymin}}}] While this works well in isolation, combining with the plot makes it sensitive to arrow head sizes. $\endgroup$
    – rm -rf
    Mar 10, 2014 at 16:46
  • $\begingroup$ @rm-rf Yeah, that's really good. Thanks. $\endgroup$
    – C. E.
    Mar 10, 2014 at 21:30
5
$\begingroup$

The following function allows you to place one arrow anywhere along a line within a set of points:

arrowedline[pts_, where_: 0.75] := {
  Line@pts, [email protected],
  Arrow /@ 
   Most@Flatten[({##, ## + where (RotateLeft[##] - ##)} &@pts), {2}]
  }

Example:

p = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}};

Mathematica graphics

You can change the direction of the arrows by changing the order of the points. Additional work is needed to streamline customizing the arrowheads.

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.