Reverse color of overlapping points?
Perhaps:
Graphics[FilledCurve[{
{Line@close@CirclePoints[{0, 0}, 1, 30]},
{Line@close@CirclePoints[{1, 1}, 1, 30]}
}]]
More generally:
close[path_List] := Append[path, First@path];
drawIt[points_List, r_: 2] :=
FilledCurve[{Line@close@CirclePoints[#, r, 40]} & /@ points];
SeedRandom[0];
Graphics[drawIt[RandomReal[{-20, 20}, {20, 2}]]]
Here's a refinement of Michael's FilledCurve
idea, where I use BSplineCurve
to generate the circles instead of Line
. The following function creates a BSplineCurve
that renders as a circle with center c
and radius r
, where r
is measure in points, and not plot coordinates (using points means that the shape of the circle is unaffected by changes in the AspectRatio
of a graphic):
splineCircle[c_, r_] := BSplineCurve[
Table[Offset[r {Cos[n Pi/4], Sin[n Pi/4]} If[OddQ[n], Sec[Pi/4], 1], c], {n, 0, 8}],
SplineDegree -> 2,
SplineKnots -> {0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4},
SplineWeights -> {1, 1/Sqrt[2], 1, 1/Sqrt[2], 1, 1/Sqrt[2], 1, 1/Sqrt[2], 1}
]
Using the above primitive, we can construct the desired output using FilledCurve:
overlappedPoints[pts_, size_] := FilledCurve @ Map[
{splineCircle[#, size]}&,
pts
]
Simple example:
Graphics[overlappedPoints[{{0, 0}, {.1, .1}}, 50], PlotRange->{{-.5,.5},{-.5,.5}}]
More points (using @Michael's example):
SeedRandom[0];
pts = RandomReal[{-20, 20}, {20, 2}];
g = Graphics[
{
overlappedPoints[pts, 9]
},
ImageSize->200
]
Here's how the graphic changes with changing aspect ratio:
GraphicsRow[
{Show[g, AspectRatio->1/2], g, Show[g, AspectRatio->2]},
ImageSize->600,
Frame->All
]
And a fairly large example (with 1000 points):
SeedRandom[0];
pts = RandomReal[{-20, 20}, {1000, 2}];
g = Graphics[
{
overlappedPoints[pts, 7]
},
ImageSize->500
]
Addendum
If you want to be able to specify the overlap colors, a small change to my original code will allow you to do this:
overlappedPoints[pts_,size_]:={
Red,
Map[Disk[#, Offset[size]]&,pts],
Black,
FilledCurve@Map[{splineCircle[#,size]}&,pts]
}
For example:
SeedRandom[0];
pts = RandomReal[{-20,20},{20,2}];
g = Graphics[{overlappedPoints[pts,9]}, ImageSize->200, AspectRatio->1/2]
where I also changed the aspect ratio to show that the points don't get elongated when the aspect ratio is changed. This approach is pretty quick even for a 1000 points.
SeedRandom[0];
pts = RandomReal[{-20,20},{1000,2}];
Graphics[{overlappedPoints[pts,7]},ImageSize->500] //AbsoluteTiming
Another way using regions.
If we have two regions defined by disks
R = {r1, r2} = {Disk[{0, 0}, 2], Disk[{1, 1}, 2]};
Graphics[R]
we can effectively paint their intersection.
Show[
Graphics[R],
MeshPrimitives[
DiscretizeRegion[RegionIntersection @@ R],
2
] /. reg : Polygon[_] :> {EdgeForm[White], White, reg} // Graphics,
PlotRange -> All
]
and, while it's almost painfully slow, for a general set of points.
overlaps[pts : {{_, _} ..}, r_: 1] := Block[
{regs},
regs = Disk[#, r] & /@ pts;
Show[
Graphics[regs],
Graphics[
Join @@ (
MeshPrimitives[DiscretizeRegion@#, 2] & /@ DeleteCases[
RegionIntersection @@@ Join @@ Table[
regs[[{j, k}]],
{j, Length@regs},
{k, Range[Length@regs]~Complement~{j}}
],
EmptyRegion[2]
]
) /. reg : Polygon[_] :> {EdgeForm[White], White, reg}
],
PlotRange -> All
]
]
SeedRandom[1234]
overlaps[RandomReal[{0, 10}, {15, 2}]]