-- |-- Module : Graphics.Rendering.Chart.Plot.AreaSpots-- Copyright : (c) Malcolm Wallace 2009-- License : BSD-style (see COPYRIGHT file)---- Area spots are a collection of unconnected filled circles,-- with x,y position, and an independent z value to be represented-- by the relative area of the spots.{-# OPTIONS_GHC -XTemplateHaskell #-}moduleGraphics.Rendering.Chart.Plot.AreaSpots(AreaSpots(..),defaultAreaSpots,area_spots_title,area_spots_linethick,area_spots_linecolour,area_spots_fillcolour,area_spots_max_radius,area_spots_values,AreaSpots4D(..),defaultAreaSpots4D,area_spots_4d_title,area_spots_4d_linethick,area_spots_4d_palette,area_spots_4d_max_radius,area_spots_4d_values)whereimportqualifiedGraphics.Rendering.CairoasCimportGraphics.Rendering.Chart.TypesimportGraphics.Rendering.Chart.Plot.TypesimportGraphics.Rendering.Chart.AxisimportData.Accessor.TemplateimportData.ColourimportData.Colour.NamesimportControl.Monad-- stuff that belongs in Data.Tuplefst3(a,_,_)=asnd3(_,a,_)=athd3(_,_,a)=afst4(a,_,_,_)=asnd4(_,a,_,_)=athd4(_,_,a,_)=afth4(_,_,_,a)=a-- | A collection of unconnected spots, with x,y position, and an-- independent z value to be represented by the area of the spot.dataAreaSpotszxy=AreaSpots{area_spots_title_::String,area_spots_linethick_::Double,area_spots_linecolour_::AlphaColourDouble,area_spots_fillcolour_::AlphaColourDouble,area_spots_max_radius_::Double-- ^ the largest size of spot,area_spots_values_::[(x,y,z)]}defaultAreaSpots::AreaSpotszxydefaultAreaSpots=AreaSpots{area_spots_title_="",area_spots_linethick_=0.1,area_spots_linecolour_=opaqueblue,area_spots_fillcolour_=flipwithOpacity0.2blue,area_spots_max_radius_=20-- in pixels,area_spots_values_=[]}instance(PlotValuez)=>ToPlot(AreaSpotsz)wheretoPlotp=Plot{plot_render_=renderAreaSpotsp,plot_legend_=[(area_spots_title_p,renderSpotLegendp)],plot_all_points_=(mapfst3(area_spots_values_p),mapsnd3(area_spots_values_p))}renderAreaSpots::(PlotValuez)=>AreaSpotszxy->PointMapFnxy->CRender()renderAreaSpotsppmap=preserveCState$forM_(scaleMax((area_spots_max_radius_p)^2)(area_spots_values_p))(\(x,y,z)->doletradius=sqrtzlet(CairoPointStyledrawSpotAt)=filledCirclesradius(area_spots_fillcolour_p)drawSpotAt(pmap(LValuex,LValuey))let(CairoPointStyledrawOutlineAt)=hollowCirclesradius(area_spots_linethick_p)(area_spots_linecolour_p)drawOutlineAt(pmap(LValuex,LValuey)))wherescaleMax::PlotValuez=>Double->[(x,y,z)]->[(x,y,Double)]scaleMaxnpoints=letlargest=maximum(map(toValue.thd3)points)scalev=n*toValuev/largestinmap(\(x,y,z)->(x,y,scalez))pointsrenderSpotLegend::AreaSpotszxy->Rect->CRender()renderSpotLegendpr@(Rectp1p2)=preserveCState$doletradius=min(abs(p_yp1-p_yp2))(abs(p_xp1-p_xp2))centre=linearInterpolatep1p2let(CairoPointStyledrawSpotAt)=filledCirclesradius(area_spots_fillcolour_p)drawSpotAtcentrelet(CairoPointStyledrawOutlineAt)=hollowCirclesradius(area_spots_linethick_p)(area_spots_linecolour_p)drawOutlineAtcentrewherelinearInterpolate(Pointx0y0)(Pointx1y1)=Point(x0+abs(x1-x0)/2)(y0+abs(y1-y0)/2)-- | A collection of unconnected spots, with x,y position, an-- independent z value to be represented by the area of the spot,-- and in addition, a fourth variable t to be represented by a colour-- from a given palette. (A linear transfer function from t to palette-- is assumed.)dataAreaSpots4Dztxy=AreaSpots4D{area_spots_4d_title_::String,area_spots_4d_linethick_::Double,area_spots_4d_palette_::[ColourDouble],area_spots_4d_max_radius_::Double-- ^ the largest size of spot,area_spots_4d_values_::[(x,y,z,t)]}defaultAreaSpots4D::AreaSpots4DztxydefaultAreaSpots4D=AreaSpots4D{area_spots_4d_title_="",area_spots_4d_linethick_=0.1,area_spots_4d_palette_=[blue,green,yellow,orange,red],area_spots_4d_max_radius_=20-- in pixels,area_spots_4d_values_=[]}instance(PlotValuez,PlotValuet,Showt)=>ToPlot(AreaSpots4Dzt)wheretoPlotp=Plot{plot_render_=renderAreaSpots4Dp,plot_legend_=[(area_spots_4d_title_p,renderSpotLegend4Dp)],plot_all_points_=(mapfst4(area_spots_4d_values_p),mapsnd4(area_spots_4d_values_p))}renderAreaSpots4D::(PlotValuez,PlotValuet,Showt)=>AreaSpots4Dztxy->PointMapFnxy->CRender()renderAreaSpots4Dppmap=preserveCState$forM_(scaleMax((area_spots_4d_max_radius_p)^2)(length(area_spots_4d_palette_p))(area_spots_4d_values_p))(\(x,y,z,t)->doletradius=sqrtzletcolour=(area_spots_4d_palette_p)!!tlet(CairoPointStyledrawSpotAt)=filledCirclesradius(flipwithOpacity0.2colour)drawSpotAt(pmap(LValuex,LValuey))let(CairoPointStyledrawOutlineAt)=hollowCirclesradius(area_spots_4d_linethick_p)(opaquecolour)drawOutlineAt(pmap(LValuex,LValuey)))wherescaleMax::(PlotValuez,PlotValuet,Showt)=>Double->Int->[(x,y,z,t)]->[(x,y,Double,Int)]scaleMaxncpoints=letlargest=maximum(map(toValue.thd4)points)scalev=n*toValuev/largestcolVals=map(toValue.fth4)pointscolMin=minimumcolValscolMax=maximumcolValsselectt=min(c-1)$truncate(fromIntegralc*(toValuet-colMin)/(colMax-colMin))inmap(\(x,y,z,t)->(x,y,scalez,selectt))pointsrenderSpotLegend4D::AreaSpots4Dztxy->Rect->CRender()renderSpotLegend4Dpr@(Rectp1p2)=preserveCState$doletradius=min(abs(p_yp1-p_yp2))(abs(p_xp1-p_xp2))centre=linearInterpolatep1p2let(CairoPointStyledrawSpotAt)=filledCirclesradius(flipwithOpacity0.2$head(area_spots_4d_palette_p))drawSpotAtcentrelet(CairoPointStyledrawOutlineAt)=hollowCirclesradius(area_spots_4d_linethick_p)(opaque$head(area_spots_4d_palette_p))drawOutlineAtcentrewherelinearInterpolate(Pointx0y0)(Pointx1y1)=Point(x0+abs(x1-x0)/2)(y0+abs(y1-y0)/2)--------------------------------------------------------------------------- Template haskell to derive Data.Accessor.Accessor$(deriveAccessors''AreaSpots)$(deriveAccessors''AreaSpots4D)