Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Is it possible to define new graphics directives?

For example, suppose I want to be able to use the following code:

Graphics[{ BigPointSize[0.07], SmallPointSize[0.04],
           Red, BigPoint[{1,1}], BigPoint[{1,3}], SmallPoint[{3,1}],
           Blue, SmallPoint[{2,2}], SmallPoint[{3,2}], BigPoint[{0,0}]
        }]

Is there any way to define BigPointSize, SmallPointSize, BigPoint, and SmallPoint so that this code will work as intended? Ideally BigPointSize and SmallPointSize should have all of the functionality of other graphics directives, e.g. scoping inside of lists, and the ability to call the command multiple times within the same list.

(Obviously it's possible to draw these points in other ways, but I'm curious whether it's possible to get this syntax to work.)

Edit: Just to clarify, I would like BigPointSize and SmallPointSize to work the same way as PointSize and other graphics directives. For example, the code

Graphics[{ BigPointSize[0.1],
           { BigPointSize[0.05], BigPoint[{0,0}] },
           BigPoint[{1,0}]
        }]

should produce one point of size 0.05 and one point of size 0.1.

share|improve this question
add comment

2 Answers

up vote 5 down vote accepted
Protect[BigPointSize, BigPoint, SmallPointSize, SmallPoint];

UserGraphics[gr_, opt : OptionsPattern[Graphics]] := Module[
  {
    BigPointSizeStack, BigPointSizeExec, BigPointExec,
    SmallPointSizeStack, SmallPointSizeExec, SmallPointExec,
    TempList, TempListExec,
  },

  BigPointSizeStack = {0.1};  (* default value *)
  BigPointSizeExec[s_] := (BigPointSizeStack[[-1]] = s; {});
  BigPointExec[p_] := {PointSize[BigPointSizeStack[[-1]]], Point[p]};

  SmallPointSizeStack = {0.1};(* default value *)
  SmallPointSizeExec[s_] := (SmallPointSizeStack[[-1]] = s; {});
  SmallPointExec[p_] := {PointSize[SmallPointSizeStack[[-1]]], Point[p]};

  TempListExec[x___] := Module[{retval},
    AppendTo[BigPointSizeStack, BigPointSizeStack[[-1]]];
    AppendTo[SmallPointSizeStack, SmallPointSizeStack[[-1]]];

    retval = {x} /. {
                      BigPointSize -> BigPointSizeExec,
                      SmallPointSize -> SmallPointSizeExec,
                      BigPoint -> BigPointExec,
                      SmallPoint -> SmallPointExec
                    };

   BigPointSizeStack = Delete[BigPointSizeStack, -1];
   BigPointSizeStack = Delete[SmallPointSizeStack, -1];
   retval
   ];

  Graphics[(gr //. x_List :> TempList @@ x) /. TempList :> TempListExec, opt]
]




gr = {Line[{{0, -1}, {6, 0}}], BigPoint[{1, 0}], BigPointSize[0.02], 
      BigPoint[{2, 0}], {BigPointSize[0.03], BigPoint[{3, 0}], Red, 
      BigPointSize[0.04], BigPoint[{4, 0}]}, BigPoint[{5, 0}]};



UserGraphics[gr, Frame -> True, PlotRange -> {{0, 6}, {-1, 1}}]

I don't belive, but I wrote it, and it works !!!

I tried to use obvious tricks and commands, which easily can be found in the documentation. The function UserGraphics supports all options and properties of Graphics. It also supports BigPointSize, SmallPointSize directives, and BigPoint, SmallPoint primitives.

It is the first version, so all found bugs/questions/comments/remarks are welcome !

share|improve this answer
    
This looks almost right, but the code under "Edit" in my original question (but with UserGraphics instead of graphics) is producing two points of the same size. –  Jim Belk Sep 22 '13 at 1:46
    
No, they are not the same size. –  Vahagn Poghosyan Sep 22 '13 at 1:52
    
Let us check. Please show me the output of the command InputForm[UserGraphics[...]] –  Vahagn Poghosyan Sep 22 '13 at 1:57
1  
Ok, I restarted the kernel and it's working for me now. It must have been because I evaluated your previous code snippet and didn't ClearAll the symbols. Thanks a lot for the answer! –  Jim Belk Sep 22 '13 at 4:20
add comment
BigPointSizeValue = 1;

BigPointSize[s_] := (BigPointSizeValue = s;)

BigPoint[p_] := {PointSize[BigPointSizeValue], Point[p]}

SmallPointSizeValue = 1;

SmallPointSize[s_]:=(SmallPointSizeValue = s;)

SmallPoint[p_] := {PointSize[SmallPointSizeValue], Point[p]}
share|improve this answer
    
Thanks for the answer. This works for the given code snippet, but it doesn't have the other properties of graphics directives, such as scoping within lists. –  Jim Belk Sep 21 '13 at 20:54
1  
No problem, just declare them like this: BigPoint[p_] := Sequence[PointSize[BigPointSizeValue], Point[p]] –  Vahagn Poghosyan Sep 21 '13 at 20:57
1  
I think without a "preprocessor" function it is impossible to inform to a given BigPointSize[...] at what level of the list it is called. If there is no built-in method to add Directives, we should use Graphics with preprocessiong function in this form Graphics[proc[gr]]. –  Vahagn Poghosyan Sep 21 '13 at 21:23
1  
Do you like the idea of preprocessor? If yes, I can write a draft version of the code. –  Vahagn Poghosyan Sep 21 '13 at 22:00
1  
It sounds like a preprocessor would work well, especially if it is possible to redefine the Graphics command to include the preprocessing. If it's not too much trouble, I'd love to see some possible code. –  Jim Belk Sep 21 '13 at 22:21
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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