public void Render(KdNode <IVector> tree, Pair <int, int> projection, string filename, double width, double height, double linewidth, double pointsize) { using (Cairo.Surface surface = CreateSurface(filename, width, height)) { using (Cairo.Context gr = new Cairo.Context(surface)) { Cairo.Color black = new Cairo.Color(0, 0, 0); Cairo.Color green = new Cairo.Color(0, 0.4, 0); Cairo.Color white = new Cairo.Color(1, 1, 1); gr.LineWidth = linewidth; gr.Antialias = Cairo.Antialias.Default; // Background gr.Color = white; gr.Rectangle(0, 0, width, height); gr.Fill(); gr.Stroke(); // Prepare for world to surface rendering CairoRenderer cr = new CairoRenderer(); cr.SetupWorldToSurfaceTransform(tree.InternalBounds, projection, width, height, true); // Render world bounds gr.Color = black; cr.RenderAABB(tree.InternalBounds, gr); gr.Stroke(); // Render leaves gr.Color = green; foreach (KdNode <IVector> iv in tree.Leaves) { cr.RenderPoints(iv.Vectors, gr, pointsize); } gr.Stroke(); // Render intermediates gr.Color = black; foreach (KdNode <IVector> n in tree.PreOrder) { if (n.Intermediate) { AABB split_bounds = n.SplitBounds; if (n.SplitDimension == projection.First) { Vector from = Vector.Create(n.SplitLocation, split_bounds.Lower[projection.Second]); Vector to = Vector.Create(n.SplitLocation, split_bounds.Upper[projection.Second]); cr.RenderLine(from, to, gr); } else if (n.SplitDimension == projection.Second) { Vector from = Vector.Create(split_bounds.Lower[projection.First], n.SplitLocation); Vector to = Vector.Create(split_bounds.Upper[projection.First], n.SplitLocation); cr.RenderLine(from, to, gr); } } } gr.Stroke(); if (_render_image) { surface.WriteToPng(filename); } else { gr.ShowPage(); } } } }