I want to build a function, where the inputs are points and voronoimesh, and points. But, the output would be a graphics parameter. the code is following:

   pts = ImageCorners[img4, MaxFeatures -> 20];
   Vmesh = VoronoiMesh[pts];
   cluster1[{pts, Vmesh}]
   cluster1[{pts_, Vmesh_}] := Block[{t16, t17},
   t16 = Graphics[{Green, {PointSize[0.05], Point[pts]}, Blue, 
   MeshPrimitives[Vmesh, 1], {Opacity[0.1], 
  EdgeForm[{Thick, Yellow}], FaceForm[Yellow]}}];
   t17 = Graphics[{Thick, Green, 
  Show[img4, t16, t17]

Here, img4 can be any image. Please choose any image.

But, this is not working when I am showing the image. How to solve the problem? It must have to be done with function.


Here's how I would change your code, if I actually understand what you intend:

(* Load a sample image to work on *)
img4 = ExampleData[{"TestImage", "Aerial"}];

(* This is your code *)
pts = ImageCorners[img4, MaxFeatures -> 20];
Vmesh = VoronoiMesh[pts];

(* This is modified to avoid localized variables *)
(* and to use a single Graphics expression *)
cluster1[{pts_, Vmesh_}] :=
   Green, PointSize[0.05], Point[pts],
   Blue, MeshPrimitives[Vmesh, 1],
   Thick, Green, Line[pts[[Last[FindShortestTour[pts]] ] ]] 

(* Show your results *)
Show[img4, cluster1[{pts, Vmesh}]]

Mathematica graphics

The main reason why your code was not working was scoping: you had localized your variables t16 and t17 within Block so they were not accessible from outside your cluster1 function.

Additionally, you did not really need to have two Graphics expressions; you can use a single long one containing all your graphics objects and directives.

Finally, the last three directives in your Graphics expression for t16 referred to no object and were unused ({Opacity[0.1], EdgeForm[{Thick, Yellow}], FaceForm[Yellow]}). Were you perhaps missing a graphics object there?


Since you would like to retain the separation between the two Graphics objects, you can still create them separately within cluster1 and assign them to internal module variables, then return them in a list from the cluster1 function, and assign them to any global variables you want.

In principle, you could also modify the t16 and t17 global variables directly from within the cluster1 function, but I'd advise against that: it may become hard to track possible bugs if your functions have such side effects.

For instance, the following code will return the same exact result as the version presented above:

cluster1[{pts_, Vmesh_}] :=
   {a, b},
   a = Graphics[{
        Green, {PointSize[0.05], Point[pts]},
        Blue, MeshPrimitives[Vmesh, 1]
   b = Graphics[{Thick, Green, Line[pts[[Last[FindShortestTour[pts]]]]]}];
   {a, b}

{t16, t17} = cluster1[{pts, Vmesh}];
Show[img4, t16, t17]
| improve this answer | |
  • $\begingroup$ Hi Marco, Thanks a lot. Actually, my purpose of this question is to learn when there are variables like t16,t17 how the functions can work. It's because, I have a very big code where before the graphics values I some calculation then the final output is some graphics value. Here, I just give a small demonstration. Also, I need them separated; not in one image for my research. So, I really want to know, is there any way, I can do it with the variables? $\endgroup$ – Odrisso Mar 12 '16 at 20:13
  • $\begingroup$ @Odrisso Yes it can certainly be done; please take a look at the updated code at then end of my answer above. $\endgroup$ – MarcoB Mar 12 '16 at 20:24
  • $\begingroup$ Hi Marco, The code is giving the following error: Could not combine the graphics objects in Show[.....] $\endgroup$ – Odrisso Mar 12 '16 at 20:37
  • $\begingroup$ @Odrisso Do you have assigned values for img4, pts and Vmesh? Try clearing these variables and then re-running their assignments, i.e. the first three lines of the first version of my answer. $\endgroup$ – MarcoB Mar 12 '16 at 20:58
  • $\begingroup$ HI, Thanks. It worked. However, I have another minor problem. It is not related to graphics. The problem is: in my function, I used some calculation and where some redundant second brackets come. Now, to remove those redundant brackets, I used "PP1 = PP1 //. {x_List} :> x" one. The problem is this gives the following error: "Tag Times in PP1 {} is Protected". How can I solve this one? $\endgroup$ – Odrisso Mar 12 '16 at 21:07

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