Custom label for ValueAxis, JFreeChart - jfreechart

I am having labels after my bars(not displayed here) which result in a longer range of values then wanted(i.e. would like to remove "125" in this case).
How can I remove the last value in my ValueAxis/RangeAxis(NumberAxis?)?
First thought I could just remove the highest value with Overriding the refreshTicks() method like this: JFreechart: Displaying X axis with values after specific units
But I lost the empty space with that one. Then I thought I could Override the "drawTickMarksAndLabels" method:
ValueAxis axis = new ValueAxis(plot.getDomainAxis().getLabel(),
null) {
#Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2,
double cursor, Rectangle2D plotArea,
Rectangle2D dataArea, RectangleEdge edge) {
// changes
}
plot.setRangeAxis(axis);
The problem with this one is that I get NullpointerException when not specifying TickUnitSource. Any idea how I can give a correct TickUnitSource to a custom ValueAxis?
Source code:
public class BarChartDemo extends ApplicationFrame {
/**
* Creates a new demo instance.
*
* #param title the frame title.
*/
public BarChartDemo(final String title) {
super(title);
final CategoryDataset dataset = createDataset();
final JFreeChart chart = createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(500, 270));
setContentPane(chartPanel);
}
/**
* Returns a sample dataset.
*
* #return The dataset.
*/
private CategoryDataset createDataset() {
// row keys...
final String series1 = "First";
// column keys...
final String category1 = "Category 1";
final String category2 = "Category 2";
final String category3 = "Category 3";
// create the dataset...
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(70.0, series1, category1);
dataset.addValue(40.0, series1, category2);
dataset.addValue(100.0, series1, category3);
return dataset;
}
/**
* Creates a sample chart.
*
* #param dataset the dataset.
*
* #return The chart.
*/
private JFreeChart createChart(final CategoryDataset dataset) {
// create the chart...
final JFreeChart chart = ChartFactory.createBarChart(
"Bar Chart Demo", // chart title
"Category", // domain axis label
"%", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
false, // include legend
false, // tooltips?
false // URLs?
);
CategoryPlot plot = chart.getCategoryPlot();
final int maxPercent = 100;
// Adding some extra space
NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
rangeAxis.setRange(0, maxPercent+(maxPercent*0.4));
// ValueAxis axis = new ValueAxis(plot.getRangeAxis().getLabel(),
// null) {
//
// #Override
// protected AxisState drawTickMarksAndLabels(Graphics2D g2,
// double cursor, Rectangle2D plotArea,
// Rectangle2D dataArea, RectangleEdge edge) {
//
// AxisState state = new AxisState(cursor);
//
// if (isAxisLineVisible()) {
// drawAxisLine(g2, cursor, dataArea, edge);
// }
//
// double ol = getTickMarkOutsideLength();
// double il = getTickMarkInsideLength();
//
// List ticks = refreshTicks(g2, state, dataArea, edge);
// state.setTicks(ticks);
// g2.setFont(getTickLabelFont());
// Iterator iterator = ticks.iterator();
// while (iterator.hasNext()) {
// ValueTick tick = (ValueTick) iterator.next();
// if (isTickLabelsVisible()) {
// g2.setPaint(getTickLabelPaint());
// float[] anchorPoint = calculateAnchorPoint(
// tick, cursor, dataArea, edge);
//
// System.out.println(tick.getText());
//
// TextUtilities.drawRotatedString(tick.getText(),
// g2, anchorPoint[0], anchorPoint[1],
// tick.getTextAnchor(), tick.getAngle(),
// tick.getRotationAnchor());
// }
//
// if (isTickMarksVisible()) {
// float xx = (float) valueToJava2D(
// tick.getValue(), dataArea, edge);
// Line2D mark = null;
// g2.setStroke(getTickMarkStroke());
// g2.setPaint(getTickMarkPaint());
// if (edge == RectangleEdge.LEFT) {
// mark = new Line2D.Double(cursor - ol, xx,
// cursor + il, xx);
// } else if (edge == RectangleEdge.RIGHT) {
// mark = new Line2D.Double(cursor + ol, xx,
// cursor - il, xx);
// } else if (edge == RectangleEdge.TOP) {
// mark = new Line2D.Double(xx, cursor - ol,
// xx, cursor + il);
// } else if (edge == RectangleEdge.BOTTOM) {
// mark = new Line2D.Double(xx, cursor + ol,
// xx, cursor - il);
// }
// g2.draw(mark);
// }
// }
//
// // need to work out the space used by the tick labels...
// // so we can update the cursor...
// double used = 0.0;
// if (isTickLabelsVisible()) {
// if (edge == RectangleEdge.LEFT) {
// used += findMaximumTickLabelWidth(ticks, g2,
// plotArea, isVerticalTickLabels());
// state.cursorLeft(used);
// } else if (edge == RectangleEdge.RIGHT) {
// used = findMaximumTickLabelWidth(ticks, g2,
// plotArea, isVerticalTickLabels());
// state.cursorRight(used);
// } else if (edge == RectangleEdge.TOP) {
// used = findMaximumTickLabelHeight(ticks, g2,
// plotArea, isVerticalTickLabels());
// state.cursorUp(used);
// } else if (edge == RectangleEdge.BOTTOM) {
// used = findMaximumTickLabelHeight(ticks, g2,
// plotArea, isVerticalTickLabels());
// state.cursorDown(used);
// }
// }
//
// return state;
// }
//
// #Override
// protected void autoAdjustRange() {
// // TODO Auto-generated method stub
//
// }
//
// #Override
// public double java2DToValue(double arg0, Rectangle2D arg1,
// RectangleEdge arg2) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// #Override
// public double valueToJava2D(double arg0, Rectangle2D arg1,
// RectangleEdge arg2) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// #Override
// public void configure() {
// // TODO Auto-generated method stub
//
// }
//
// #Override
// public AxisState draw(Graphics2D arg0, double arg1,
// Rectangle2D arg2, Rectangle2D arg3,
// RectangleEdge arg4, PlotRenderingInfo arg5) {
// // TODO Auto-generated method stub
// return null;
// }
//
// #Override
// public List refreshTicks(Graphics2D arg0, AxisState arg1,
// Rectangle2D arg2, RectangleEdge arg3) {
// // TODO Auto-generated method stub
// return null;
// }
// };
//
// plot.setRangeAxis(axis);
return chart;
}
public static void main(final String[] args) {
final BarChartDemo demo = new BarChartDemo("Bar Chart Demo");
demo.pack();
demo.setVisible(true);
}
}

Managed to remove the last value by:
NumberAxis rangeAxis = new NumberAxis() {
#Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2,
double cursor, Rectangle2D plotArea, Rectangle2D dataArea,
RectangleEdge edge) {
// CHANGES
}
plot.setRangeAxis(rangeAxis);

Related

My unity save system doesn't save integer array

I don't get any errors but my script doesn't load or possibly save my array...
here's the first script
[System.Serializable]
public class PlayerData
{
public float health;
public float thirst;
public float hunger;
public float oxygen;
public float[] position;
public int[] inventoryIDs;
public PlayerData (Health healthO, SaveLoad saveload)
{
//Save int items
health = healthO.health;
thirst = healthO.thirst;
hunger = healthO.hunger;
oxygen = healthO.oxygen;
//set and save location array
position = new float[3];
position[0] = healthO.transform.position.x;
position[1] = healthO.transform.position.y;
position[2] = healthO.transform.position.z;
//set and save inventory IDs
inventoryIDs = new int[50];
for(int i = 0; i < 50; i++)
{
inventoryIDs[i] = saveload.IDs[i];
}
}
}
here's the next
public class SaveLoad : MonoBehaviour
{
public GameObject player;
public int[] IDs;
public GameObject[] objects;
Inventory inventory;
Health health;
void Start()
{
IDs = new int[50];
objects = new GameObject[50];
inventory = player.GetComponent<Inventory>();
health = player.GetComponent<Health>();
}
void Update()
{
//Add IDs
for (int i = 0; i < 50; i++)
{
IDs[i] = inventory.slot[i].GetComponent<Slot>().ID;
}
//debug save load test
if (Input.GetKeyDown(KeyCode.Z))
{
SaveP();
}
if (Input.GetKeyDown(KeyCode.X))
{
LoadP();
}
}
public void SaveP()
{
SaveSystem.SavePlayer(health, this);
}
public void LoadP()
{
PlayerData data = SaveSystem.LoadPlayer();
//load stats
health.thirst = data.thirst;
health.hunger = data.hunger;
health.health = data.health;
health.oxygen = data.oxygen;
//Load position
Vector3 position;
position.x = data.position[0];
position.y = data.position[1];
position.z = data.position[2];
player.transform.position = position;
//load IDs
for (int i = 0; i < 50; i++)
{
IDs[i] = data.inventoryIDs[i];
}
//Load Items
for (int i = 0; i < 50; i++)
{
if(objects[IDs[i]] != null)
{
GameObject itemObject = (GameObject)Instantiate(objects[IDs[i]], new Vector3(0, 0, 0), Quaternion.identity);
Item item = itemObject.GetComponent<Item>();
inventory.AddItem(itemObject, item.ID, item.type, item.name, item.description, item.icon);
} else
{
return;
}
}
}
}
Here's the last script
public static class SaveSystem
{
public static string fileName = "FileSave.bin";
public static void SavePlayer(Health health, SaveLoad SL)
{
//Create formatter
BinaryFormatter bf = new BinaryFormatter();
// Create file stream
FileStream file = File.Create(GetFullPath());
//Save data
PlayerData data = new PlayerData(health, SL);
bf.Serialize(file, data);
//Close stream
file.Close();
}
public static PlayerData LoadPlayer()
{
if (SaveExists())
{
try
{
//Create formatter
BinaryFormatter bf = new BinaryFormatter();
//Create file stream
FileStream file = File.Open(GetFullPath(), FileMode.Open);
//Load data
PlayerData pd = (PlayerData)bf.Deserialize(file);
//close stream
file.Close();
//return data
return pd;
}
catch (SerializationException)
{
Debug.Log("Failed to load file at: " + GetFullPath());
}
}
return null;
}
private static bool SaveExists()
{
return File.Exists(GetFullPath());
}
private static string GetFullPath()
{
return Application.persistentDataPath + "/" + fileName;
}
}
there are all connected with the save load script loading and saving the variables into the player and items to the inventory sots. the inventory IDs array isn't saving or loading

Graphic view of binary tree in Windows Forms

I have to make a graphical representation of a binary tree with the possibility of selecting nodes...Any ideas?
It should look like this
binary tree
I might translate this later for a quick, working example in C#, but here is a Java homework assignment I did way back in 2000!
You should be able to glean the algorithm and code necessary to draw the Tree based on the Java class:
// FileName: DrawBinaryTree.java
/************************************
* Student: Michael Tomlinson *
* Course: CS 145-Section 1 *
* Instructor: Dareleen Schaffer *
* *
* Assignment #4, Problem #1 *
* Due Date: July 24, 2000 *
************************************
*/
package BinaryTree;
import java.awt.*;
import javax.swing.*;
public class DrawBinaryTree {
// Data Fields
private BinaryTree tree=null;
private double xDiv=50, yDiv=50;
private boolean sizeToFit=true;
private Panel outputPanel=null;
// Constructors
public DrawBinaryTree() {} // default constructor
public DrawBinaryTree(BinaryTree tree) {
setBinaryTree(tree);
} // end constructor with (BinaryTree) parameters
public DrawBinaryTree(Panel panel) {
setOutputPanel(panel);
} // end constructor with (JPanel) parameters
public DrawBinaryTree(BinaryTree tree, Panel panel) {
setBinaryTree(tree);
setOutputPanel(panel);
} // end constructor with (BinaryTree, JPanel) parameters
// Modifiers
public void setBinaryTree(BinaryTree tree) {
this.tree = tree;
} // end method setBinaryTree
public void setOutputPanel(Panel panel) {
this.outputPanel = panel;
} // end method setOutputPanel
public void setSizeToFit(boolean sizeToFit) {
this.sizeToFit = sizeToFit;
} // end method setSizeToFit
public void increaseXDiv() {
xDiv*=1.1;
} // end method increaseXDiv
public void increaseYDiv() {
yDiv*=1.1;
} // end method increaseYDiv
public void decreaseXDiv() {
xDiv*=.9;
} // end method decreaseXDiv
public void decreaseYDiv() {
yDiv*=.9;
} // end method decreaseyDiv
// Public Methods
public void drawTree(Point translate) {
if(outputPanel!=null && tree!=null) {
Graphics g = outputPanel.getGraphics();
g.translate(translate.x, translate.y);
Dimension panelSize = outputPanel.getSize();
if(!tree.isEmpty()) {
int treeDepth = tree.maxLevel();
if(sizeToFit) {
xDiv = (double)panelSize.width/(Math.pow(2,treeDepth+1)+1);
yDiv = (double)panelSize.height/((double)treeDepth+1);
}
Point rootCoord = new Point(panelSize.width/2, (int)(yDiv/2));
drawTreeNode(rootCoord, tree.getRoot(), 0, g);
}
else {
Font f = g.getFont();
String message = "The Tree is Empty.";
FontMetrics fm = g.getFontMetrics(f);
int messageLength = fm.stringWidth(message);
int messageHeight = fm.getHeight();
g.drawString(message, panelSize.width/2 - messageLength/2,
panelSize.height/2 - messageHeight/2);
}
g.dispose();
}
} // end method drawTree
// Private Methods
private void drawTreeNode(Point coord, SearchTreeNode node, int depth,
Graphics g) {
double xOffset = (Math.pow(2, tree.maxLevel() - depth)/2)*xDiv;
int newY =(int)(((double)depth+1)*yDiv+yDiv/2.0);
if(node.leftChild!=null) {
int lcx = (int)(coord.x - xOffset);
g.setColor(Color.blue);
g.drawLine(coord.x, coord.y, lcx, newY);
Point leftChildCoord = new Point(lcx, newY);
drawTreeNode(leftChildCoord, node.leftChild, (depth + 1), g);
}
if(node.rightChild!=null) {
int rcx = (int)(coord.x + xOffset);
g.setColor(Color.red);
g.drawLine(coord.x, coord.y, rcx, newY);
Point rightChildCoord = new Point(rcx, newY);
drawTreeNode(rightChildCoord, node.rightChild, (depth + 1), g);
}
g.setColor(Color.black);
g.drawOval(coord.x-5, coord.y-5, 10, 10);
g.fillOval(coord.x-5, coord.y-5, 10, 10);
g.drawString(node.item.toString(), coord.x+10, coord.y+5);
} // end method drawTreeNode
} // end class DrawBinary Tree

Update Jfreechart when update data from Webcam

My jfreeChart comes from frames of a webcam. I pass this frames and it generates a graphic of R, G and B colors of this frame. I want this chart do automatic update as I pass the frames. I've tried everything but nothing seens to work.
Any help is welcome.
class DaemonThread implements Runnable
{
protected volatile boolean runnable = false;
#Override
public void run()
{
synchronized(this)
{
while(runnable)
{
if(webSource.grab())
{
try
{
webSource.retrieve(frame);
Imgcodecs.imencode(".bmp", frame, mem);
Image im = ImageIO.read(new ByteArrayInputStream(mem.toArray()));
buff = (BufferedImage) im;
if(contHistograma==0) {
h = new Histo(buff);
contHistograma++;
}else{
h.update(buff);
}
webcamLabel.setIcon(new ImageIcon(buff));
Graphics g=webcamPanel.getGraphics();
if (g.drawImage(buff, 0, 0, getWidth(), getHeight() -150 , 0, 0, buff.getWidth(), buff.getHeight(), null))
if(runnable == false)
{
System.out.println("Going to wait()");
this.wait();
}
}
catch(Exception ex)
{
System.out.println("Error");
}
}
}
}
}
}
public class Histo{
private ChartFrame lineFrame;
private ArrayList<Integer> redArray;
private ArrayList<Integer> greenArray;
private ArrayList<Integer> blueArray;
public Histo(BufferedImage originalImage){
Color c;
redArray = new ArrayList<>();
greenArray = new ArrayList<>();
blueArray = new ArrayList<>();
for (int i = 0; i < originalImage.getWidth(null); i++) {
for (int j = 0; j < originalImage.getHeight(null); j++) {
c = new Color(originalImage.getRGB(i,j));
redArray.add(c.getRed());
greenArray.add(c.getGreen());
blueArray.add(c.getBlue());
}
}
Collections.sort(redArray);
Collections.sort(greenArray);
Collections.sort(blueArray);
XYSeriesCollection dataset = creatingDataset(redArray, greenArray, blueArray);
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart);
lineFrame = new ChartFrame("teste", chart);
lineFrame.add(chartPanel);
lineFrame.setVisible(true);
lineFrame.setSize(600, 450);
}
public void update(BufferedImage originalImage){
redArray.clear();
greenArray.clear();
blueArray.clear();
Color c;
for (int i = 0; i < originalImage.getWidth(null); i++) {
for (int j = 0; j < originalImage.getHeight(null); j++) {
c = new Color(originalImage.getRGB(i,j));
redArray.add(c.getRed());
greenArray.add(c.getGreen());
blueArray.add(c.getBlue());
}
}
Collections.sort(redArray);
Collections.sort(greenArray);
Collections.sort(blueArray);
XYSeriesCollection dataset = creatingDataset(redArray, greenArray, blueArray);
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart);
lineFrame.removeAll();
lineFrame.add(chartPanel);
lineFrame.revalidate();
lineFrame.setLayout(new BorderLayout());
lineFrame.repaint();
}
public static XYSeriesCollection creatingDataset(ArrayList<Integer> redArray,ArrayList<Integer> greenArray,ArrayList<Integer> blueArray){
int cont=1, cont2=1, cont3=1;
XYSeries series = new XYSeries("Red");
XYSeries series2 = new XYSeries("Green");
XYSeries series3 = new XYSeries("Blue");
for (int i = 0; i < redArray.size()-1; i++) {
if(redArray.get(i).intValue() == redArray.get(i+1).intValue()) {
cont++;
}else{
series.add(redArray.get(i).intValue(), cont);
cont=1;
}
}
for (int i = 0; i < greenArray.size()-1; i++) {
if(greenArray.get(i).intValue() == greenArray.get(i + 1).intValue()) {
cont2++;
}else{
series2.add(greenArray.get(i).intValue(), cont2);
cont2 = 1;
}
}
for (int i = 0; i < blueArray.size()-1; i++) {
if(blueArray.get(i).intValue() == blueArray.get(i+1).intValue()) {
cont3++;
}else{
series3.add(blueArray.get(i).intValue(), cont3);
cont3=1;
}
}
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
dataset.addSeries(series2);
dataset.addSeries(series3);
return dataset;
}
private JFreeChart createChart(final XYDataset dataset) {
JFreeChart result = ChartFactory.createXYLineChart("Gráfico XY", "Eixo X", "Eixo Y", dataset, PlotOrientation.VERTICAL, true, true, false);
final XYPlot plot = result.getXYPlot();
plot.setBackgroundPaint(new Color(0xffffe0));
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.lightGray);
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.lightGray);
final NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis(); //RANGE EIXO X
domainAxis.setRange(0, 260);
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); //RANGE EIXO Y
rangeAxis.setRange(0, 5000);
return result;
}
}
If someone else have this problem here is the answer:
Chartframe can't get rid of chartpanel, so I made Chartpanel a atribute.
After that I update my dataset and did this:
JFreeChart chart = createChart(dataset);
chartPanel.setChart(chart);
lineFrame.setLayout(new BorderLayout());
lineFrame.repaint();
Problem solved.

Sound either loops, or plays once and once only

Ok, so I'm having problems playing my wav sounds in the most efficient way as possible. IF I get rid of the 'clip.setFramePosition' in my Audio class, then the sound loops (obviously because the clip keeps reversing back to frame 0). IF I take away the 'clip.setFramePosition' method, the sound plays ONCE, and once only (probably because it needs to be set BACK to it's original frame position).
Two classes are involved:
/**
* Initalise sound clips
*/
public static Clip reverb = loadClip("/SFX_Intro/reverb.wav");
public static Clip glitch = loadClip("/SFX_Intro/glitch.wav");
public static Clip menu = loadClip("/SFX_Ambience/menu.wav");
/*
* audio input to enable sound
*/
private static AudioInputStream ais;
/**
* load sound clip
*/
private static Clip loadClip(String resourceName) {
try {
ais = AudioSystem.getAudioInputStream(Audio.class.getResource(resourceName));
DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
return clip;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* play sound clip
*/
public static void play(Clip clip) {
if (clip != null) {
try {
clip.rewind();
clip.setFramePosition(0);
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* loop sound
*/
public static void loop(Clip clip, int amount) {
if (clip != null) {
try {
clip.loop(amount);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Stop sound
*/
public static void stop(Clip clip) {
clip.stop();
}
and...
/**
* alpha vars
*/
private int alpha = 220;
private final int MIN_ALPHA = 0;
private Color c;
private Rectangle r;
/**
* class importations
*/
private Counter[] delay;
/**
* Constructor
*/
public Intro(GameStateManager gsm) {
super(gsm);
delay = new Counter[3];
delay[0] = new Counter();
delay[1] = new Counter();
delay[2] = new Counter();
}
/**
* Update
*/
public void update() {
Cursor.setCursor(Cursor.INVISIBLE);
}
/**
* Draw
*/
public void draw(Graphics2D g) {
delay[2].count(2);
if (delay[2].bFinished) {
r = new Rectangle(0, 0, GamePanel.WIDTH, GamePanel.HEIGHT);
c = new Color(0, 0, 0, alpha);
g.drawImage(Texture.plogo_01, GamePanel.WIDTH / 2
- Texture.plogo_01.getWidth() / 2, GamePanel.HEIGHT / 2
- Texture.plogo_01.getHeight() / 2, null);
if (alpha != MIN_ALPHA) {
alpha -= 1;
}
else if (alpha == MIN_ALPHA) { // Once faded in...
g.drawImage(Texture.plogo_02, GamePanel.WIDTH / 2
- Texture.plogo_02.getWidth() / 2, GamePanel.HEIGHT / 2
- Texture.plogo_02.getHeight() / 2, null);
delay[0].count(0.005); // set delay time
Audio.play(Audio.glitch); // Play glitch sound
}
if (delay[0].bFinished) { // Once delay time has finished...
g.setColor(Color.BLACK);
g.fill(r);
delay[1].count(3); // set another delay time
if (delay[1].bFinished) {
gsm.setState(GameStateManager.MENU); // change to menu state
return;
}
}
g.setColor(c);
g.fill(r);
}
}
/**
* Key input
*/
public void keyPressed(int key) {
}
public void keyReleased(int key) {
}
I hope someone can help solve this problem. Thank you in advance.
Solved. I added an 'if' statement inside the 'Play' method:
public static void play(Clip clip) {
try {
clip.start();
int MAX_FRAMES = clip.getFrameLength();
if (clip.getFramePosition() == MAX_FRAMES) {
clip.setFramePosition(0);
stop(clip);
}
} catch (Exception e) {
e.printStackTrace();
}
return;
}

WPF 3D POINT DRAWING

I need to draw a point in 3D using WPF. I am using class ScreenSpaceLines3D to draw a line in 3D, but I'm not able to draw point in 3D (while model zooming). Can anybody help me? Some example code would be appreciated. Thanks
Use PointsVisual3D class from helixtoolkit, with it you can add points on viewport with color, size. Even you can apply transforms, too.
A point can't be seen, because it has no surface area. WPF 3d is not a ray tracing engine, unfortunately.
However, someone built a pretty nice ray-tracing starter library. This project is a good starting point if you want to do ray-tracing with WPF: http://raytracer.codeplex.com/.
It is not so complicated task.
Download the Helix3D Library
Find the sphere mesh code in samples
Attach the scphere's radius to zooming realization.
i can create a PointVisual3d Own Class. The code of PointVisual3D is below i think this one is helpful for you...
public class PointVisual3D:ModelVisual3D
{
private readonly GeometryModel3D _model;
private readonly MeshGeometry3D _mesh;
private Matrix3D _visualToScreen;
private Matrix3D _screenToVisual;
public PointVisual3D()
{
_mesh = new MeshGeometry3D();
_model = new GeometryModel3D();
_model.Geometry = _mesh;
SetColor(this.Color);
this.Content = _model;
this.Points = new Point3DCollection();
CompositionTarget.Rendering += OnRender;
}
private void OnRender(object sender, EventArgs e)
{
if (Points.Count == 0 && _mesh.Positions.Count == 0)
{
return;
}
if (UpdateTransforms() && MainWindow.mousedown==false)
{
RebuildGeometry();
}
}
public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(PointVisual3D), new PropertyMetadata(Colors.White, OnColorChanged));
private static void OnColorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((PointVisual3D)sender).SetColor((Color)args.NewValue);
}
private void SetColor(Color color)
{
MaterialGroup unlitMaterial = new MaterialGroup();
unlitMaterial.Children.Add(new DiffuseMaterial(new SolidColorBrush(Colors.Black)));
unlitMaterial.Children.Add(new EmissiveMaterial(new SolidColorBrush(color)));
unlitMaterial.Freeze();
_model.Material = unlitMaterial;
_model.BackMaterial = unlitMaterial;
}
public Color Color
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
//public static readonly DependencyProperty ThicknessProperty = DependencyProperty.Register("Thickness", typeof(double), typeof(PointVisual3D), new PropertyMetadata(1.0, OnThicknessChanged));
//private static void OnThicknessChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
//{
// ((PointVisual3D)sender).GeometryDirty();
//}
//public double Thickness
//{
// get { return (double)GetValue(ThicknessProperty); }
// set { SetValue(ThicknessProperty, value); }
//}
public static readonly DependencyProperty PointsProperty = DependencyProperty.Register("Points", typeof(Point3DCollection), typeof(PointVisual3D), new PropertyMetadata(null, OnPointsChanged));
private static void OnPointsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((PointVisual3D)sender).GeometryDirty();
}
public Point3DCollection Points
{
get { return (Point3DCollection)GetValue(PointsProperty); }
set { SetValue(PointsProperty, value); }
}
private void GeometryDirty()
{
_visualToScreen = MathUtils.ZeroMatrix;
}
private void RebuildGeometry()
{
//double halfThickness = Thickness / 2.0;
//int numLines = Points.Count / 2;
//Point3DCollection positions = new Point3DCollection(numLines * 4);
//for (int i = 0; i < numLines; i++)
//{
// int startIndex = i * 2;
// Point3D startPoint = Points[startIndex];
// Point3D endPoint = Points[startIndex + 1];
// AddSegment(positions, startPoint, endPoint, halfThickness);
//}
//positions.Freeze();
//_mesh.Positions = positions;
Int32Collection indices = new Int32Collection(Points.Count * 6);
for (int i = 0; i < Points.Count; i++)
{
indices.Add(i * 4 + 2);
indices.Add(i * 4 + 1);
indices.Add(i * 4 + 0);
indices.Add(i * 4 + 2);
indices.Add(i * 4 + 3);
indices.Add(i * 4 + 1);
}
indices.Freeze();
_mesh.TriangleIndices = indices;
_mesh.Positions = CreatePositions(this.Points, this.Size, 0.0);
}
public Point3DCollection CreatePositions(IList<Point3D> points, double size = 1.0, double depthOffset = 0.0)
{
double halfSize = size / 2.0;
int numPoints = points.Count;
var outline = new[]
{
new Vector(-halfSize, halfSize), new Vector(-halfSize, -halfSize), new Vector(halfSize, halfSize),
new Vector(halfSize, -halfSize)
};
var positions = new Point3DCollection(numPoints * 4);
for (int i = 0; i < numPoints; i++)
{
var screenPoint = (Point4D)points[i] * this._visualToScreen;
double spx = screenPoint.X;
double spy = screenPoint.Y;
double spz = screenPoint.Z;
double spw = screenPoint.W;
if (!depthOffset.Equals(0))
{
spz -= depthOffset * spw;
}
var p0 = new Point4D(spx, spy, spz, spw) * this._screenToVisual;
double pwinverse = 1 / p0.W;
foreach (var v in outline)
{
var p = new Point4D(spx + v.X * spw, spy + v.Y * spw, spz, spw) * this._screenToVisual;
positions.Add(new Point3D(p.X * pwinverse, p.Y * pwinverse, p.Z * pwinverse));
}
}
positions.Freeze();
return positions;
}
/// <summary>
/// Identifies the <see cref="Size"/> dependency property.
/// </summary>
public static readonly DependencyProperty SizeProperty = DependencyProperty.Register(
"Size", typeof(double), typeof(PointVisual3D), new UIPropertyMetadata(1.0, GeometryChanged));
protected static void GeometryChanged(object sender, DependencyPropertyChangedEventArgs e)
{
((PointVisual3D)sender).GeometryDirty();
}
public double Size
{
get
{
return (double)this.GetValue(SizeProperty);
}
set
{
this.SetValue(SizeProperty, value);
}
}
//private void AddSegment(Point3DCollection positions, Point3D startPoint, Point3D endPoint, double halfThickness)
//{
// Vector3D lineDirection = endPoint * _visualToScreen - startPoint * _visualToScreen;
// lineDirection.Z = 0;
// lineDirection.Normalize();
// Vector delta = new Vector(-lineDirection.Y, lineDirection.X);
// delta *= halfThickness;
// Point3D pOut1, pOut2;
// Widen(startPoint, delta, out pOut1, out pOut2);
// positions.Add(pOut1);
// positions.Add(pOut2);
// Widen(endPoint, delta, out pOut1, out pOut2);
// positions.Add(pOut1);
// positions.Add(pOut2);
//}
//private void Widen(Point3D pIn, Vector delta, out Point3D pOut1, out Point3D pOut2)
//{
// Point4D pIn4 = (Point4D)pIn;
// Point4D pOut41 = pIn4 * _visualToScreen;
// Point4D pOut42 = pOut41;
// pOut41.X += delta.X * pOut41.W;
// pOut41.Y += delta.Y * pOut41.W;
// pOut42.X -= delta.X * pOut42.W;
// pOut42.Y -= delta.Y * pOut42.W;
// pOut41 *= _screenToVisual;
// pOut42 *= _screenToVisual;
// pOut1 = new Point3D(pOut41.X / pOut41.W, pOut41.Y / pOut41.W, pOut41.Z / pOut41.W);
// pOut2 = new Point3D(pOut42.X / pOut42.W, pOut42.Y / pOut42.W, pOut42.Z / pOut42.W);
//}
private bool UpdateTransforms()
{
Viewport3DVisual viewport;
bool success;
Matrix3D visualToScreen = MathUtils.TryTransformTo2DAncestor(this, out viewport, out success);
if (!success || !visualToScreen.HasInverse)
{
_mesh.Positions = null;
return false;
}
if (visualToScreen == _visualToScreen)
{
return false;
}
_visualToScreen = _screenToVisual = visualToScreen;
_screenToVisual.Invert();
return true;
}
}

Resources