public BeanTopologieFacettes GetTopologieVoronoiByDicoPoints(Dictionary <int, Point> p_dicoPointsAvecId, int p_srid, enumVoronoiStrategiePointsDupliques p_strategieSiDuplication = enumVoronoiStrategiePointsDupliques.arretTraitement) { BeanTopologieFacettes v_topol = new BeanTopologieFacettes(); try { BeanAlimentationVoronoi v_BeanDAlimentation = GetBeanAlimentationVoronoiByDicoPoints(p_dicoPointsAvecId, p_srid); v_BeanDAlimentation.p12_parametrage.gestionPointsDupliques = p_strategieSiDuplication; if (!v_BeanDAlimentation.p22_contientObjetsInvalidesVf) { VoronoiGraph v_voronoiGraph = GetVoronoiGraph(v_BeanDAlimentation); v_topol = GetBeanTopologieByVoronoiGraph(v_voronoiGraph, v_BeanDAlimentation); } } catch (Exception v_ex) { throw v_ex; } return(v_topol); }
public BeanTopologieFacettes GetTopologieVoronoiByDicoPointsEtMbo(Dictionary <int, Point> p_dicoPointsAvecId, double[] p_coodMinMaxXy, int p_srid) { BeanTopologieFacettes v_topol = new BeanTopologieFacettes(); try { BeanAlimentationVoronoi v_BeanDAlimentation = GetBeanAlimentationVoronoiByDicoPointsEtMbo(p_dicoPointsAvecId, p_coodMinMaxXy, p_srid); if (!v_BeanDAlimentation.p22_contientObjetsInvalidesVf) { VoronoiGraph v_voronoiGraph = GetVoronoiGraph(v_BeanDAlimentation); v_topol = GetBeanTopologieByVoronoiGraph(v_voronoiGraph, v_BeanDAlimentation); } } catch (Exception) { throw; } return(v_topol); }
// public BeanTriangulationDelaunay GetTriangulationDeDelaunayByDicoPoints(Dictionary <int, Point> p_dicoPointsAvecId, int p_srid) { BeanTriangulationDelaunay v_trOut = null; try { BeanAlimentationVoronoi v_BeanDAlimentation = GetBeanAlimentationVoronoiByDicoPoints(p_dicoPointsAvecId, p_srid); v_BeanDAlimentation.p12_parametrage.gestionPointsDupliques = enumVoronoiStrategiePointsDupliques.deduplicationAleatoire; if (!v_BeanDAlimentation.p22_contientObjetsInvalidesVf) { VoronoiGraph v_voronoiGraph = GetVoronoiGraph(v_BeanDAlimentation); v_trOut = GetTriangulationDelaunayByVoronoiGraph(v_voronoiGraph, v_BeanDAlimentation); //Je remets la source d'origine, par "sécurité" v_trOut.p00_PointIGeometrySources = p_dicoPointsAvecId; // } } catch (Exception v_ex) { throw v_ex; } return(v_trOut); }
//public BeanTopologie GetBeanTopologieByVoronoiGraph(VoronoiGraph p_voronoiGraph, BeanAlimentationVoronoi p_beanAlimentationVoronoi) //{ // BeanTopologie v_topologieVoronoi = new BeanTopologie(); // try // { // Dictionary<int, BeanArc_internal> v_arcs = new Dictionary<int, BeanArc_internal>(); // Dictionary<int, int> v_DicoPointSourceGaucheParArc = new Dictionary<int, int>(); // Dictionary<int, int> v_DicoPointSourceDroitParArc = new Dictionary<int, int>(); // //Création du réseau // BeanTopologie v_topologieLignes = new BeanTopologie(); // double v_vorX_Left; // double v_vorY_Left; // double v_vorX_Right; // double v_vorY_Right; // double v_OrigX_Left; // double v_OrigY_Left; // double v_OrigX_Right; // double v_OrigY_Right; // double v_CorrectionX = 0; // double v_CorrectionY = 0; // ITopologieService v_topologieService = new TopologieService(); // IGeometry v_line; // String v_CodeXYPointGauche; // String v_CodeXYPointDroit; // int v_KeyPointGauche; // int v_KeyPointDroit; // int v_KeyArc = 0; // HashSet<string> v_testDoublesLignes = new HashSet<string>(); // string v_codeLigne; // if (p_beanAlimentationVoronoi.parametrage.reductionCoordonneesVf) // { // v_CorrectionX = (double)p_beanAlimentationVoronoi.origineXCorrigee; // v_CorrectionY = (double)p_beanAlimentationVoronoi.origineYCorrigee; // } // foreach (VoronoiEdge v_Edges in p_voronoiGraph.Edges) // { // if (!v_Edges.IsInfinite && !v_Edges.IsPartlyInfinite) // { // v_KeyArc++; // //Je créé des variables intermédiaires car modifierLaGeometrie directement le vecteur pose graves pb // v_vorX_Left = v_Edges.VVertexA[0] + v_CorrectionX; // v_vorY_Left = v_Edges.VVertexA[1] + v_CorrectionY; // v_vorX_Right = v_Edges.VVertexB[0] + v_CorrectionX; // v_vorY_Right = v_Edges.VVertexB[1] + v_CorrectionY; // v_OrigX_Left = v_Edges.LeftData[0] + v_CorrectionX; // v_OrigY_Left = v_Edges.LeftData[1] + v_CorrectionY; // v_OrigX_Right = v_Edges.RightData[0] + v_CorrectionX; // v_OrigY_Right = v_Edges.RightData[1] + v_CorrectionY; // // // v_line = v_topologieService.GetLineStringByCoord(v_vorX_Left, v_vorY_Left, v_vorX_Right, v_vorY_Right); // if (v_line.Length > 0) // { // v_CodeXYPointGauche = GetCodeXY(v_OrigX_Left, v_OrigY_Left); // v_CodeXYPointDroit = GetCodeXY(v_OrigX_Right, v_OrigY_Right); // //J'ai rencontré des duplications de lignes (dans un sens et dans l'autre) // //Ces cas provoquent des boucles sans fin dans la fermeture d'îlots // // Je mets un patch : A réintégrer DANS TOPOLOGIE SERVICE // if (v_OrigX_Left < v_OrigX_Right) // { // v_codeLigne = v_CodeXYPointGauche + "_" + v_CodeXYPointDroit; // } // else // { // if (v_OrigX_Left == v_OrigX_Right) // { // if (v_OrigY_Left < v_OrigY_Right) // { // v_codeLigne = v_CodeXYPointGauche + "_" + v_CodeXYPointDroit; // } // else // { v_codeLigne = v_CodeXYPointDroit + "_" + v_CodeXYPointGauche; } // } // else // { v_codeLigne = v_CodeXYPointDroit + "_" + v_CodeXYPointGauche; } // } // //Si la ligne est déjà contenue, je ne l'introduis pas // if (v_testDoublesLignes.Contains(v_codeLigne)) { break; } // // // v_arcs.Add(v_KeyArc, v_line); // v_KeyPointGauche = -1; // if (p_beanAlimentationVoronoi.dicoLienCodeXyKeySource.ContainsKey(v_CodeXYPointGauche)) // { // p_beanAlimentationVoronoi.dicoLienCodeXyKeySource.TryGetValue(v_CodeXYPointGauche, out v_KeyPointGauche); // } // v_DicoPointSourceGaucheParArc.Add(v_KeyArc, v_KeyPointGauche); // v_KeyPointDroit = -1; // if (p_beanAlimentationVoronoi.dicoLienCodeXyKeySource.ContainsKey(v_CodeXYPointGauche)) // { // p_beanAlimentationVoronoi.dicoLienCodeXyKeySource.TryGetValue(v_CodeXYPointDroit, out v_KeyPointDroit); // } // v_DicoPointSourceDroitParArc.Add(v_KeyArc, v_KeyPointDroit); // } // }//Fin if (!v_Edges.IsInfinite && !v_Edges.IsPartlyInfinite) // }//Fin foreach // //Création de la topologie // v_topologieLignes = v_topologieService.GetTopologie(v_arcs); // ////STRUCTURATION en ILOTS: // //v_topologieVoronoi = v_topologieService.GetTopologieSansImpassesEnrichiesDesIlots(v_topologieLignes); // //v_topologieService.MiseAJourDesIndicateursDeControleTopologieIlot(v_topologieVoronoi); // ////Renumérotation des îlots // //v_topologieService.UpdateIdIlotsByCotesArcs(v_topologieVoronoi, v_DicoPointSourceDroitParArc, v_DicoPointSourceGaucheParArc); // ////FIN STRUCTURATION en ILOTS: // } // catch (Exception v_ex) // { // throw v_ex; // } // return v_topologieVoronoi; //} public BeanTriangulationDelaunay GetTriangulationDelaunayByVoronoiGraph(VoronoiGraph p_voronoiGraph, BeanAlimentationVoronoi p_beanAlimentationVoronoi) { BeanTriangulationDelaunay v_triangulationDelaunay = new BeanTriangulationDelaunay(); try { //[Je filtre les id négatifs: correspondent au Mbo de construction foreach (KeyValuePair <int, Point> v_pointsOriginels in p_beanAlimentationVoronoi.p10_dicoDesPointsSources) { if (v_pointsOriginels.Key >= 0) { v_triangulationDelaunay.p00_PointIGeometrySources.Add(v_pointsOriginels.Key, v_pointsOriginels.Value); } } // double v_OrigX_Left; double v_OrigY_Left; double v_OrigX_Right; double v_OrigY_Right; double v_CorrectionX = 0; double v_CorrectionY = 0; // if (p_beanAlimentationVoronoi.p12_parametrage.reductionCoordonneesVf) { v_CorrectionX = (double)p_beanAlimentationVoronoi.p55_origineXCorrigee; v_CorrectionY = (double)p_beanAlimentationVoronoi.p56_origineYCorrigee; } BeanArcDelaunay v_arcDelaunay; string v_CodeXYPointGauche; string v_CodeXYPointDroit; ITopologieService v_topologieService = new TopologieService(); int v_cleDroite; int v_cleGauche; int v_KeyArc = 0; foreach (VoronoiEdge v_Edges in p_voronoiGraph.Edges) { if (!v_Edges.IsInfinite && !v_Edges.IsPartlyInfinite) { v_KeyArc++; v_OrigX_Left = v_Edges.LeftData[0] + v_CorrectionX; v_OrigY_Left = v_Edges.LeftData[1] + v_CorrectionY; v_OrigX_Right = v_Edges.RightData[0] + v_CorrectionX; v_OrigY_Right = v_Edges.RightData[1] + v_CorrectionY; // //v_CodeXYPointGauche = GetCodeXY(v_OrigX_Left, v_OrigY_Left); v_CodeXYPointGauche = FLabServices.createUtilitaires().GetHCodeGeogPoint(new double[2] { v_OrigX_Left, v_OrigY_Left }); //v_CodeXYPointDroit = GetCodeXY(v_OrigX_Right, v_OrigY_Right); v_CodeXYPointDroit = FLabServices.createUtilitaires().GetHCodeGeogPoint(new double[2] { v_OrigX_Right, v_OrigY_Right }); // if (p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint.ContainsKey(v_CodeXYPointGauche) && p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint.ContainsKey(v_CodeXYPointDroit)) { v_cleGauche = p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint[v_CodeXYPointGauche]; v_cleDroite = p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint[v_CodeXYPointDroit]; if (v_cleDroite >= 0 && v_cleGauche >= 0) { v_arcDelaunay = new BeanArcDelaunay(); v_arcDelaunay.p11_idPoint1 = v_cleGauche; v_arcDelaunay.p21_coordPoint1[0] = v_OrigX_Left; v_arcDelaunay.p21_coordPoint1[1] = v_OrigY_Left; // v_arcDelaunay.p12_idPoint2 = v_cleDroite; v_arcDelaunay.p22_coordPoint2[0] = v_OrigX_Right; v_arcDelaunay.p22_coordPoint2[1] = v_OrigY_Right; // v_arcDelaunay.p00_codeArcDelaunay = GetHCodeArcDelaunay(v_cleGauche, v_cleDroite, true); // v_arcDelaunay.p30_arcDelaunay = v_topologieService.GetLineStringByCoord(v_OrigX_Left, v_OrigY_Left, v_OrigX_Right, v_OrigY_Right); v_triangulationDelaunay.p01_arcsDelaunay.Add(v_arcDelaunay); } } } } } catch (Exception v_ex) { throw v_ex; } return(v_triangulationDelaunay); }
public BeanTopologieFacettes GetBeanTopologieByVoronoiGraph(VoronoiGraph p_voronoiGraph, BeanAlimentationVoronoi p_beanAlimentationVoronoi) { BeanTopologieFacettes v_topologie = new BeanTopologieFacettes(); try { List <BeanArc_internal> v_arcsVoronoi = new List <BeanArc_internal>(); Dictionary <string, BeanArc_internal> v_arcsParHCode = new Dictionary <string, BeanArc_internal>(); int v_srid = p_beanAlimentationVoronoi.p11_srid; // Dictionary <string, BeanPoint_internal> v_pointsDesArcsByCode = new Dictionary <string, BeanPoint_internal>(); Dictionary <int, BeanArc_internal> v_arcs = new Dictionary <int, BeanArc_internal>(); Dictionary <int, int> v_DicoPointSourceGaucheParArc = new Dictionary <int, int>(); Dictionary <int, int> v_DicoPointSourceDroitParArc = new Dictionary <int, int>(); // //Création du réseau double v_vorX_Left; double v_vorY_Left; double v_vorX_Right; double v_vorY_Right; double v_OrigX_Left; double v_OrigY_Left; double v_OrigX_Right; double v_OrigY_Right; double v_CorrectionX = 0; double v_CorrectionY = 0; ITopologieService v_topologieService = new TopologieService(); int v_KeyArc = 0; HashSet <string> v_testDoublesLignes = new HashSet <string>(); if (p_beanAlimentationVoronoi.p12_parametrage.reductionCoordonneesVf) { v_CorrectionX = (double)p_beanAlimentationVoronoi.p55_origineXCorrigee; v_CorrectionY = (double)p_beanAlimentationVoronoi.p56_origineYCorrigee; } BeanPoint_internal v_pt1; BeanPoint_internal v_pt2; BeanArc_internal v_arc; //On créé une facette/ilot pour chaque point; BeanFacette_internal v_facette; Dictionary <int, BeanFacette_internal> v_toutesFacettes; v_toutesFacettes = p_beanAlimentationVoronoi.p10_dicoDesPointsSources.ToDictionary(c => c.Key, c => new BeanFacette_internal()); //[ATTENTION! On doit mettre à jour l'id foreach (KeyValuePair <int, BeanFacette_internal> v_fac in v_toutesFacettes) { v_fac.Value.p00_idFacette = v_fac.Key; } //On parcourt les arcs: string v_hcodePt1; string v_hcodePt2; string v_hcodeGraineVoronoiAGauche; string v_hcodeGraineVoronoiADroite; int v_idIlotAGauche; int v_idIlotADroite; foreach (VoronoiEdge v_Edges in p_voronoiGraph.Edges) { if (!v_Edges.IsInfinite && !v_Edges.IsPartlyInfinite) { v_KeyArc++; //L'arc voronoi v_vorX_Left = v_Edges.VVertexA[0] + v_CorrectionX; v_vorY_Left = v_Edges.VVertexA[1] + v_CorrectionY; v_vorX_Right = v_Edges.VVertexB[0] + v_CorrectionX; v_vorY_Right = v_Edges.VVertexB[1] + v_CorrectionY; // v_hcodePt1 = FLabServices.createUtilitaires().GetHCodeGeogPoint(new double[2] { v_vorX_Left, v_vorY_Left }); if (v_pointsDesArcsByCode.ContainsKey(v_hcodePt1)) { v_pt1 = v_pointsDesArcsByCode[v_hcodePt1]; } else { v_pt1 = new BeanPoint_internal(v_vorX_Left, v_vorY_Left, 0, v_srid); v_pointsDesArcsByCode.Add(v_hcodePt1, v_pt1); } // v_hcodePt2 = FLabServices.createUtilitaires().GetHCodeGeogPoint(new double[2] { v_vorX_Right, v_vorY_Right }); if (v_pointsDesArcsByCode.ContainsKey(v_hcodePt2)) { v_pt2 = v_pointsDesArcsByCode[v_hcodePt2]; } else { v_pt2 = new BeanPoint_internal(v_vorX_Right, v_vorY_Right, 0, v_srid); v_pointsDesArcsByCode.Add(v_hcodePt2, v_pt2); } // v_arc = new BeanArc_internal(v_pt1, v_pt2); // if (!v_arcsParHCode.ContainsKey(v_arc.p01_hcodeArc)) { v_arcsParHCode.Add(v_arc.p01_hcodeArc, v_arc); } //On référence les points 'graines' voronoi à droite et à gauche v_OrigX_Left = v_Edges.LeftData[0] + v_CorrectionX; v_OrigY_Left = v_Edges.LeftData[1] + v_CorrectionY; v_OrigX_Right = v_Edges.RightData[0] + v_CorrectionX; v_OrigY_Right = v_Edges.RightData[1] + v_CorrectionY; // v_hcodeGraineVoronoiAGauche = FLabServices.createUtilitaires().GetHCodeGeogPoint(new double[2] { v_OrigX_Left, v_OrigY_Left }); v_hcodeGraineVoronoiADroite = FLabServices.createUtilitaires().GetHCodeGeogPoint(new double[2] { v_OrigX_Right, v_OrigY_Right }); // v_facette = null; if (p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint.ContainsKey(v_hcodeGraineVoronoiAGauche)) { v_idIlotAGauche = p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint[v_hcodeGraineVoronoiAGauche]; v_facette = v_toutesFacettes[v_idIlotAGauche]; v_facette.p02_arcs.Add(v_arc); v_arc.p21_facetteGauche = v_facette; } else { v_arc.p20_statutArc = enumStatutArc.arcExterne; } v_facette = null; if (p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint.ContainsKey(v_hcodeGraineVoronoiADroite)) { v_idIlotADroite = p_beanAlimentationVoronoi.p31_correspondanceHCodePointvsIdPoint[v_hcodeGraineVoronoiADroite]; v_facette = v_toutesFacettes[v_idIlotADroite]; v_facette.p02_arcs.Add(v_arc); v_arc.p21_facetteGauche = v_facette; } else { v_arc.p20_statutArc = enumStatutArc.arcExterne; } } //Fin if (!v_Edges.IsInfinite && !v_Edges.IsPartlyInfinite) } //Fin foreach //Création de la topologie v_arcsVoronoi = v_arcsParHCode.Values.OrderBy(c => c.p01_hcodeArc).ToList(); //On actualise les points des facettes: foreach (KeyValuePair <int, BeanFacette_internal> v_fac in v_toutesFacettes) { List <BeanPoint_internal> v_points = v_fac.Value.p02_arcs.Select(c => c.p11_pointDbt).ToList(); v_points.AddRange(v_fac.Value.p02_arcs.Select(c => c.p12_pointFin).ToList()); HashSet <string> v_pointsDeja = new HashSet <string>(); foreach (BeanPoint_internal v_pt in v_points) { if (!v_pointsDeja.Contains(v_pt.p01_hCodeGeog)) { v_fac.Value.p01_pointsDeFacette.Add(v_pt); v_pointsDeja.Add(v_pt.p01_hCodeGeog); } } } // v_topologie = new BeanTopologieFacettes(v_arcsVoronoi); v_topologie.p13_facettesById = v_toutesFacettes; //On supprime les éventuelles facettes sans dimension List <int> v_idFacettesASupprimer; v_idFacettesASupprimer = v_toutesFacettes.Where(c => c.Value.p02_arcs.Count < 3).Select(c => c.Key).ToList(); BeanFacette_internal v_facetteASupprimer; foreach (int v_idFacASuppr in v_idFacettesASupprimer) { v_facetteASupprimer = v_topologie.p13_facettesById[v_idFacASuppr]; v_topologie.FacetteSupprimer(v_facetteASupprimer); } //Géométrie: List <int> v_idFacettes = v_topologie.p13_facettesById.Keys.ToList(); IGeometry v_geomFacette; BeanFacette_internal v_facettePourGeom; foreach (int v_idFac in v_idFacettes) { v_facettePourGeom = v_topologie.p13_facettesById[v_idFac]; v_geomFacette = FLabServices.createCalculMedium().GetGeometryPolygoneFacetteEtOrdonnePointsFacette(ref v_facettePourGeom, ref v_topologie); v_facettePourGeom.p04_geomFacette = v_geomFacette; } } catch (Exception v_ex) { throw v_ex; } return(v_topologie); }
public static VoronoiGraph ComputeVoronoiGraph(IEnumerable Datapoints) { BinaryPriorityQueue PQ = new BinaryPriorityQueue(); Hashtable CurrentCircles = new Hashtable(); VoronoiGraph VG = new VoronoiGraph(); VNode RootNode = null; foreach(Vector V in Datapoints) { PQ.Push(new VDataEvent(V)); } while(PQ.Count>0) { VEvent VE = PQ.Pop() as VEvent; VDataNode[] CircleCheckList; if(VE is VDataEvent) { RootNode = VNode.ProcessDataEvent(VE as VDataEvent,RootNode,VG,VE.Y,out CircleCheckList); } else if(VE is VCircleEvent) { CurrentCircles.Remove(((VCircleEvent)VE).NodeN); if(!((VCircleEvent)VE).Valid) continue; RootNode = VNode.ProcessCircleEvent(VE as VCircleEvent,RootNode,VG,VE.Y,out CircleCheckList); } else throw new Exception("Got event of type "+VE.GetType().ToString()+"!"); foreach(VDataNode VD in CircleCheckList) { if(CurrentCircles.ContainsKey(VD)) { ((VCircleEvent)CurrentCircles[VD]).Valid=false; CurrentCircles.Remove(VD); } VCircleEvent VCE = VNode.CircleCheckDataNode(VD,VE.Y); if(VCE!=null) { PQ.Push(VCE); CurrentCircles[VD]=VCE; } } if(VE is VDataEvent) { Vector DP = ((VDataEvent)VE).DataPoint; foreach(VCircleEvent VCE in CurrentCircles.Values) { if(MathTools.Dist(DP[0],DP[1],VCE.Center[0],VCE.Center[1])<VCE.Y-VCE.Center[1] && Math.Abs(MathTools.Dist(DP[0],DP[1],VCE.Center[0],VCE.Center[1])-(VCE.Y-VCE.Center[1]))>1e-10) VCE.Valid = false; } } } VNode.CleanUpTree(RootNode); foreach(VoronoiEdge VE in VG.Edges) { if(VE.Done) continue; if(VE.VVertexB == Fortune.VVUnkown) { VE.AddVertex(Fortune.VVInfinite); if(Math.Abs(VE.LeftData[1]-VE.RightData[1])<1e-10 && VE.LeftData[0]<VE.RightData[0]) { Vector T = VE.LeftData; VE.LeftData = VE.RightData; VE.RightData = T; } } } ArrayList MinuteEdges = new ArrayList(); foreach(VoronoiEdge VE in VG.Edges) { if(!VE.IsPartlyInfinite && VE.VVertexA.Equals(VE.VVertexB)) { MinuteEdges.Add(VE); // prevent rounding errors from expanding to holes foreach(VoronoiEdge VE2 in VG.Edges) { if(VE2.VVertexA.Equals(VE.VVertexA)) VE2.VVertexA = VE.VVertexA; if(VE2.VVertexB.Equals(VE.VVertexA)) VE2.VVertexB = VE.VVertexA; } } } foreach(VoronoiEdge VE in MinuteEdges) VG.Edges.Remove(VE); return VG; }
public static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList) { VDataNode a,b,c; VEdgeNode eu,eo; b = e.NodeN; a = VNode.LeftDataNode(b); c = VNode.RightDataNode(b); if(a==null || b.Parent==null || c==null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint)) { CircleCheckList = new VDataNode[]{}; return Root; // Abbruch da sich der Graph verändert hat } eu = (VEdgeNode)b.Parent; CircleCheckList = new VDataNode[] {a,c}; //1. Create the new Vertex Vector VNew = new Vector(e.Center[0],e.Center[1]); // VNew[0] = Fortune.ParabolicCut(a.DataPoint[0],a.DataPoint[1],c.DataPoint[0],c.DataPoint[1],ys); // VNew[1] = (ys + a.DataPoint[1])/2 - 1/(2*(ys-a.DataPoint[1]))*(VNew[0]-a.DataPoint[0])*(VNew[0]-a.DataPoint[0]); VG.Vertizes.Add(VNew); //2. Find out if a or c are in a distand part of the tree (the other is then b's sibling) and assign the new vertex if(eu.Left==b) // c is sibling { eo = VNode.EdgeToRightDataNode(a); // replace eu by eu's Right eu.Parent.Replace(eu,eu.Right); } else // a is sibling { eo = VNode.EdgeToRightDataNode(b); // replace eu by eu's Left eu.Parent.Replace(eu,eu.Left); } eu.Edge.AddVertex(VNew); // ///////////////////// uncertain // if(eo==eu) // return Root; // ///////////////////// //complete & cleanup eo eo.Edge.AddVertex(VNew); //while(eo.Edge.VVertexB == Fortune.VVUnkown) //{ // eo.Flipped = !eo.Flipped; // eo.Edge.AddVertex(Fortune.VVInfinite); //} //if(eo.Flipped) //{ // Vector T = eo.Edge.LeftData; // eo.Edge.LeftData = eo.Edge.RightData; // eo.Edge.RightData = T; //} //2. Replace eo by new Edge VoronoiEdge VE = new VoronoiEdge(); VE.LeftData = a.DataPoint; VE.RightData = c.DataPoint; VE.AddVertex(VNew); VG.Edges.Add(VE); VEdgeNode VEN = new VEdgeNode(VE, false); VEN.Left = eo.Left; VEN.Right = eo.Right; if(eo.Parent == null) return VEN; eo.Parent.Replace(eo,VEN); return Root; }