Sound either loops, or plays once and once only - loops

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;
}

Related

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

Naudio unvalid operation exception unhandeled

I am using Naudio in WPF for the first time.It keeps giving an exception "InvalidOperationException was unhandled".Buffer Bull.I don't know how to handle it. So far there is no error that is being shown by the debugger.
The Lines that are throwing the exception
waveFile.Write(e.Buffer, 0, e.BytesRecorded); and
sourceStream.StartRecording();
public partial class voiceNote : Window
{
public voiceNote()
{
InitializeComponent();
}
public NAudio.Wave.WaveIn waveSource = null;
public NAudio.Wave.WaveFileWriter waveFile = null;
private void resources_Click(object sender, RoutedEventArgs e)
{
List<NAudio.Wave.WaveInCapabilities> sources = new List<NAudio.Wave.WaveInCapabilities>();
for (int i = 0; i < NAudio.Wave.WaveIn.DeviceCount; i++)
{
sources.Add(NAudio.Wave.WaveIn.GetCapabilities(i));
}
//to make sure refreshed
devicesList.Items.Clear();
foreach (var source in sources)
{
//ListViewItem item;
devicesList.Items.Add(source.ProductName);
//= new ListViewItem(source.ProductName.ToString);
//item.SubItem.Add(new ListViewItem.ListViewSubItem(item, source.Channels, ToString()));
//sourceList.Items.Add(item);
}
}
//to get input....Sound Source
NAudio.Wave.WaveIn sourceStream = null;
//To sync the source of input and input audio
NAudio.Wave.DirectSoundOut waveOut = null;
// To write wve file
NAudio.Wave.WaveFileWriter waveWriter = null;
private void startRecording_Click(object sender, RoutedEventArgs e)
{
// if (devicesList.SelectedItem.Count = 0) return;
int devicenumber = devicesList.SelectedIndex;
// int devicenumber = devicesList.SelectedItems[0].index;
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = devicenumber;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(devicenumber).Channels);
NAudio.Wave.WaveInProvider waveIn = new NAudio.Wave.WaveInProvider(sourceStream);
//*****************************
//waveOut = new NAudio.Wave.DirectSoundOut();
//waveOut.Init(waveIn);
//sourceStream.StartRecording();
//waveOut.Play();
sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
// waveWriter = new NAudio.Wave.WaveFileWriter(sav.FileName, sourceStream.WaveFormat);
sourceStream.StartRecording();
}
private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
// //data is byte array, buffer, count
// waveWriter.WriteData(e.Buffer, 0, e.BytesRecorded);
// waveWriter.Flush(); //to write on disk.... so data is not held up on the ram
}
private void stopandsave_Click(object sender, RoutedEventArgs e)
{
if (waveOut != null)
{
waveOut.Stop();
waveOut.Dispose();
waveOut = null;
}
//Stop Recording
if (sourceStream != null)
{
sourceStream.StartRecording();
sourceStream.Dispose();
sourceStream = null;
}
if (waveWriter != null)
{
waveWriter.Dispose();
waveWriter = null;
}
}
}

Control Volume Code for J2ME

I have nokia xpressmusic 5130 c-2 working on symbian (j2me) the volume buttons has been broken, so i decided to make a j2me program to control the volume (increase,decrease)
I have found many codes through the internet but often not work or have many errors because not complied with the program flow diagram and screen
regards
If the device have support to the JSR 256: Mobile Sensor API, then you can use your API:
http://jcp.org/en/jsr/detail?id=256
My class that uses the JSR 256:
/*
* REVISION HISTORY:
*
* Date Author(s)
* CR Headline
* =============================================================================
* 22/Oct/2009 Douglas Daniel Del Frari
* <CR51674> Initial Version
* =============================================================================
* 25/Feb/2010 Douglas Daniel Del Frari
* <CR52577> Added more one sensor (charge state) to detection of charger state.
* =============================================================================
*/
package j2me.mobilesensor;
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.sensor.Data;
import javax.microedition.sensor.DataListener;
import javax.microedition.sensor.SensorConnection;
import javax.microedition.sensor.SensorInfo;
import javax.microedition.sensor.SensorManager;
/**
* This class uses the resource of the mobile sensor (JSR-256) to capture the
* phone battery level, and the volume level of the phone
*
* #author Douglas D. Del Frari (douglas.frari#gmail.com)
*/
public class MobileSensorManager implements DataListener, Runnable{
/** ID for the alert dialog */
public static final int ID_DIALOG_BATTERY_CHARGE = 90;
/**
* String used to get the battery charge level.
*/
private static final String BATTERY = "battery_charge";
/**
* String used to get the charger state (plugged on or off).
*/
private static final String BATTERY_CHARGER_STATE = "charger_state";
/**
* String used to get the sound level
*/
private static final String SOUND_LEVEL = "sound_level_setting";
// sensors
private static SensorConnection batterySensor = null;
private SensorConnection soundSensor = null;
// SensorInfo objects containing info about
private SensorInfo infos[];
// Is sensor thread running?
private static boolean isStopped = false;
// Buffer for the sensor data
private static final int BUFFER_SIZE = 1;
/**
* Indicate the minimal value of battery level of the game
*/
public static final int BATTERY_LIFE_LIMIT = 25;
// Thread for initializing and listening
private Thread thread = null;
/*
* Sensor quantity string received from the dataReceived() method
*/
private String sensorString = "";
// Sensor value (battery_charge)
private String batteryString = "";
private String volumeString = "";
private boolean isActiveBatterySensor;
private boolean isLowBatteryCharge;
private int batteryChargeValue;
private int volumeValue;
private SensorConnection batteryChargerState;
private boolean chargeState;
// instance this class
private static MobileSensorManager instance;
/**
* default constructor
*/
private MobileSensorManager() {
}
/**
* Get the MobileSensorManager instance
*
* #return instance this
*/
public static MobileSensorManager getInstance() {
if (instance == null) {
instance = new MobileSensorManager();
}
return instance;
}
/**
* #param stopped
*/
private synchronized void setStopped(boolean stopped) {
isStopped = stopped;
notify();
if (thread != null)
thread = null;
}
/**
* start the mobile sensors
*/
public synchronized void start() {
setStopped(false);
if (thread == null)
thread = new Thread(this);
thread.start();
}
/**
* stop the mobile sensors
*/
public synchronized void stop() {
setStopped(true);
thread = null;
}
/* (non-Javadoc)
* #see java.lang.Runnable#run()
*/
public void run() {
initSensors();
}
/**
* Initializes (opens) the sensors and sets the DataListener. Takes also
* care of removing the DataListeners and closing the connections
*/
private synchronized void initSensors() {
batterySensor = openSensor(BATTERY);
if (batterySensor == null) {
isActiveBatterySensor = false;
return;
} else {
isActiveBatterySensor = true;
}
batteryChargerState = openSensor(BATTERY_CHARGER_STATE);
soundSensor = openSensor(SOUND_LEVEL);
try {
batterySensor.setDataListener(this, BUFFER_SIZE);
if (soundSensor !=null) {
soundSensor.setDataListener(this, BUFFER_SIZE);
}
if (batteryChargerState != null) {
batteryChargerState.setDataListener(this, BUFFER_SIZE);
}
while (!isStopped) {
try {
wait();
} catch (InterruptedException ie) {
}
}
batterySensor.removeDataListener();
if (soundSensor !=null) {
soundSensor.removeDataListener();
}
if (batteryChargerState != null) {
batteryChargerState.removeDataListener();
}
} catch (IllegalMonitorStateException imse) {
imse.printStackTrace();
} catch (IllegalArgumentException iae) {
iae.printStackTrace();
}
try {
if (batterySensor!=null) {
batterySensor.close();
}
if (soundSensor !=null) {
soundSensor.close();
}
if (batteryChargerState != null) {
batteryChargerState.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
if (isStopped) {
batterySensor = null;
soundSensor = null;
batteryChargerState = null;
}
}
/**
* Searches sensors of desired quantity and if found returns a
* SensorConnection opened to it.
*
* #return SensorConnection, which has been opened to a sensor matching the
* criteria
*/
private SensorConnection openSensor(String quantity) {
infos = SensorManager.findSensors(quantity, null);
if (infos.length == 0)
return null;
String sensor_url = infos[0].getUrl();
try {
return (SensorConnection) Connector.open(sensor_url);
} catch (IOException ioe) {
ioe.printStackTrace();
return null;
}
}
/* (non-Javadoc)
* #see javax.microedition.sensor.DataListener#dataReceived(javax.microedition.sensor.SensorConnection, javax.microedition.sensor.Data[], boolean)
*/
public void dataReceived(SensorConnection sensor, Data[] data, boolean isDataLost) {
sensorString = sensor.getSensorInfo().getQuantity();
int values[] = data[0].getIntValues();
if (sensorString.equals(BATTERY)) {
setBatteryString("" + values[0] + "%");
batteryChargeValue = values[0];
}
if (sensorString.equals(SOUND_LEVEL)) {
setVolumeString("" + values[0] + " sound level");
volumeValue = values[0];
}
if (sensorString.equals(BATTERY_CHARGER_STATE)) {
int value = values[0];
if (value == 0)
chargeState = false;
else if (value == 1)
chargeState = true;
}
if (values[0] <= BATTERY_LIFE_LIMIT) {
isLowBatteryCharge = true;
} else {
isLowBatteryCharge = false;
}
}
/**
* #return the batteryString
*/
public String getBatteryString() {
return batteryString;
}
/**
* #param batteryString the batteryString to set
*/
public void setBatteryString(String batteryString) {
this.batteryString = batteryString;
}
/**
* #return the isLowBatteryCharge
*/
public boolean isLowBatteryCharge() {
return isLowBatteryCharge;
}
/**
* #return the isActiveBatterySensor
*/
public boolean isActiveBatterySensor() {
return isActiveBatterySensor;
}
/**
* #return the batteryChargeValue
*/
public int getBatteryChargeValue() {
return batteryChargeValue;
}
/**
* #param volumeString the volumeString to set
*/
public void setVolumeString(String volumeString) {
this.volumeString = volumeString;
}
/**
* #return the volumeString
*/
public String getVolumeString() {
return volumeString;
}
/**
* #param volumeValue the volumeValue to set
*/
public void setVolumeValue(int volumeValue) {
this.volumeValue = volumeValue;
}
/**
* #return the volumeValue
*/
public int getVolumeValue() {
return volumeValue;
}
/**
* Get state of battery charge
*
* #return True if the charge is plugged in, otherwise not plugged in
*/
public boolean isChargedState() {
return chargeState;
}
}

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;
}
}

How to avoid recursive dependency properties

I have a class LineG inherited from a shape which will draw a simple line between two points.. I did that simply by adding two dependency properties StartPointProperty and EndPointProperty... Lastly I want to add another functionality which is MidPoint, so when I draw the line there will be a midPoint in the middle of the line.
When I drag the StartPoint or EndPoint the shape will be redrawn, and when I drag the MidPoint the shape will translate depending on the MidPoint change...
private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LineG lineG = (LineG)d;
if (e.Property.Name == "StartPoint")
{
}
else if (e.Property.Name == "EndPoint")
{
}
else //if MidPoint
{
Point p1 = (Point)e.OldValue;
Point p2 = (Point)e.NewValue;
double offsetX = p2.X - p1.X;
double offsetY = p2.Y - p1.Y;
lineG.StartPoint = new Point(lineG.StartPoint.X + offsetX, lineG.StartPoint.Y + offsetY);
lineG.EndPoint = new Point(lineG.EndPoint.X + offsetX, lineG.EndPoint.Y + offsetY);
lineG.MidPoint = GeneralMethods.MidPoint(lineG.StartPoint, lineG.EndPoint);
}
lineG.InvalidateMeasure();
}
protected override Geometry DefiningGeometry
{
get
{
lg.StartPoint = StartPoint;
lg.EndPoint = EndPoint;
return lg;
}
}
In such cases you can add an int counter to each operation in your class that you increment during processing. You don't do something if the counter is not 0. Example:
private int _suspendCalculation;
private static void OnPropertyChanged(..)
{
if (_suspendCalculation > 0) return;
_suspendCalculation++;
try
{
CalculateAndSetOtherProperty();
}
finally
{
_suspendCalculation--;
}
}

Resources