private int GetRingSize(AtomVisual start, Point end, double bondSize) { //take the dot product of the distance we moved the mouse with the balancing vector double displacement = Vector.Multiply((end - start.Position), start.ParentAtom.BalancingVector()); return GetRingSize(bondSize, displacement); }
private void ClearTemporaries() { if (_adorner != null) { RemoveAdorner(ref _adorner); } _currentAtomVisual = null; IsDrawing = false; //clear this to prevent a weird bug in drawing CurrentEditor.ActiveChemistry = null; }
private void AtomAdded(Atom atom) { if (!chemicalVisuals.ContainsKey(atom)) //it's not already in the list { if (atom.Element is FunctionalGroup) { chemicalVisuals[atom] = new FunctionalGroupVisual(atom, ShowAtomsInColour); } else { chemicalVisuals[atom] = new AtomVisual(atom, ShowAtomsInColour, ShowImplicitHydrogens, ShowAllCarbonAtoms); } } var cv = chemicalVisuals[atom]; if (cv is FunctionalGroupVisual fgv) { if (fgv.RefCount == 0) // it hasn't been added before { fgv.ChemicalVisuals = chemicalVisuals; fgv.BackgroundColor = Background; fgv.SymbolSize = ViewModel.SymbolSize; fgv.SubscriptSize = ViewModel.SymbolSize * ViewModel.ScriptScalingFactor; fgv.SuperscriptSize = ViewModel.SymbolSize * ViewModel.ScriptScalingFactor; fgv.Standoff = ViewModel.Standoff; fgv.Render(); AddVisual(fgv); } fgv.RefCount++; } else if (cv is AtomVisual av) { if (av.RefCount == 0) // it hasn't been added before { av.ChemicalVisuals = chemicalVisuals; av.SymbolSize = ViewModel.SymbolSize; av.SubscriptSize = ViewModel.SymbolSize * ViewModel.ScriptScalingFactor; av.SuperscriptSize = ViewModel.SymbolSize * ViewModel.ScriptScalingFactor; av.BackgroundColor = Background; av.DisplayOverbonding = DisplayOverbondedAtoms; av.Render(); AddVisual(av); } av.RefCount++; } }
private void AtomAdded(Atom atom) { if (!chemicalVisuals.ContainsKey(atom)) //it's not already in the list { if (atom.Element is FunctionalGroup fg) { chemicalVisuals[atom] = new FunctionalGroupVisual(atom); } else { chemicalVisuals[atom] = new AtomVisual(atom); } } var cv = chemicalVisuals[atom]; if (cv is FunctionalGroupVisual fgv) { if (fgv.RefCount == 0) // it hasn't been added before { fgv.ChemicalVisuals = chemicalVisuals; fgv.BackgroundColor = Background; fgv.Render(); AddVisual(fgv); } fgv.RefCount++; } else if (cv is AtomVisual av) { if (av.RefCount == 0) // it hasn't been added before { av.ChemicalVisuals = chemicalVisuals; av.BackgroundColor = Background; av.Render(); AddVisual(av); } av.RefCount++; } }
private void CurrentEditor_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var position = e.GetPosition(CurrentEditor); _currentAtomVisual = CurrentEditor.GetTargetedVisual(position) as AtomVisual; if (_currentAtomVisual == null) { _angleSnapper = new Snapper(position, EditViewModel); } else { Mouse.Capture(CurrentEditor); _angleSnapper = new Snapper(_currentAtomVisual.ParentAtom.Position, EditViewModel); _lastAtomVisual = _currentAtomVisual; } IsDrawing = true; }
private void RedrawAtom(Atom atom) { int refCount = 1; AtomVisual av = null; if (chemicalVisuals.ContainsKey(atom)) { av = (AtomVisual)chemicalVisuals[atom]; refCount = av.RefCount; AtomRemoved(atom); } AtomAdded(atom); av = (AtomVisual)chemicalVisuals[atom]; av.RefCount = refCount; }
/// <summary> /// tells you where to put a new atom /// </summary> /// <param name="lastAtomVisual"></param> /// <param name="congestedPositions">Places to avoid dumping the new atom</param> /// <returns></returns> private (Point NewPos, ClockDirections sproutDir) GetNewChainEndPos(AtomVisual lastAtomVisual) { ClockDirections GetGeneralDir(Vector bondVector) { double bondAngle = Vector.AngleBetween(BasicGeometry.ScreenNorth, bondVector); ClockDirections hour = (ClockDirections)BasicGeometry.SnapToClock(bondAngle); return(hour); } var lastAtom = lastAtomVisual.ParentAtom; Vector newDirection; ClockDirections newTag; if (lastAtom.Degree == 0) //isolated atom { newDirection = ClockDirections.II.ToVector() * EditViewModel.Model.XamlBondLength; newTag = ClockDirections.II; } else if (lastAtom.Degree == 1) { Vector bondVector = lastAtom.Position - lastAtom.Neighbours.First().Position; var hour = GetGeneralDir(bondVector); if (VirginAtom(lastAtom)) //it hasn't yet sprouted { //Tag is used to store the direction the atom sprouted from its previous atom newTag = GetNewSproutDirection(hour); newDirection = newTag.ToVector() * EditViewModel.Model.XamlBondLength; } else //it has sprouted, so where to put the new branch? { var vecA = ((ClockDirections)lastAtom.Tag).ToVector(); vecA.Normalize(); var vecB = -bondVector; vecB.Normalize(); var balancingVector = -(vecA + vecB); balancingVector.Normalize(); newTag = GetGeneralDir(balancingVector); newDirection = balancingVector * EditViewModel.Model.XamlBondLength; } } else if (lastAtom.Degree == 2) { var balancingVector = lastAtom.BalancingVector(); balancingVector.Normalize(); newDirection = balancingVector * EditViewModel.Model.XamlBondLength; newTag = GetGeneralDir(balancingVector); } else //lastAtom.Degree >= 2: could get congested { FindOpenSpace(lastAtom, EditViewModel.Model.XamlBondLength, out newDirection); newTag = GetGeneralDir(newDirection); } return(newDirection + lastAtom.Position, newTag); }
public AtomHoverAdorner(UIElement adornedElement, AtomVisual targetedVisual) : this(adornedElement) { _targetedVisual = targetedVisual; }
private Geometry GetBondAdornerGeometry(Bond bond) { //work out the actual visible extent of the bond Point startPoint, endPoint; Vector unitVector = bond.BondVector; unitVector.Normalize(); AtomVisual startAtomVisual = CurrentEditor.GetAtomVisual(bond.StartAtom); AtomVisual endAtomVisual = CurrentEditor.GetAtomVisual(bond.EndAtom); Point?sp; //work out where the bond vector intersects the start and end points of the bond if (!string.IsNullOrEmpty(bond.StartAtom.SymbolText) && (sp = startAtomVisual.GetIntersection(bond.StartAtom.Position, bond.EndAtom.Position)) != null) { startPoint = sp.Value; } else { startPoint = bond.StartAtom.Position + unitVector * RenderRadius; } Point?ep; if (!string.IsNullOrEmpty(bond.EndAtom.SymbolText) && (ep = endAtomVisual.GetIntersection(bond.StartAtom.Position, bond.EndAtom.Position)) != null) { endPoint = ep.Value; } else { endPoint = bond.EndAtom.Position - unitVector * RenderRadius; } //get the perpendiculars to the bond Matrix toLeft = new Matrix(); toLeft.Rotate(-90); Matrix toRight = new Matrix(); toRight.Rotate(90); Vector right = bond.BondVector * toRight; right.Normalize(); Vector left = bond.BondVector * toLeft; left.Normalize(); //draw the rectangle on top of the bond PathFigure pathFigure = new PathFigure(); pathFigure.StartPoint = startPoint + right * RenderRadius; pathFigure.IsClosed = true; LineSegment lineSegment1 = new LineSegment(); lineSegment1.Point = startPoint + left * RenderRadius; pathFigure.Segments.Add(lineSegment1); LineSegment lineSegment2 = new LineSegment(); lineSegment2.Point = endPoint + left * RenderRadius; pathFigure.Segments.Add(lineSegment2); LineSegment lineSegment3 = new LineSegment(); lineSegment3.Point = endPoint + right * RenderRadius; pathFigure.Segments.Add(lineSegment3); //add in the figure List <PathFigure> figures = new List <PathFigure>(); figures.Add(pathFigure); //now create the geometry PathGeometry pathGeometry = new PathGeometry(figures); //work out the end caps Geometry start = new EllipseGeometry(startPoint, RenderRadius, RenderRadius); Geometry end = new EllipseGeometry(endPoint, RenderRadius, RenderRadius); //add them in CombinedGeometry result = new CombinedGeometry(GeometryCombineMode.Union, pathGeometry, start); result = new CombinedGeometry(GeometryCombineMode.Union, result, end); //and return return(result); }