private void EnSeBuscaronDuplicados(object elEnviador, EventArgs losArgumentos) { // Añade los PDIs duplicados. miLista.SuspendLayout(); miLista.Items.Clear(); miLista.Groups.Clear(); foreach (KeyValuePair <Pdi, IList <Pdi> > item in miBuscadorDeDuplicados.GruposDeDuplicados) { Pdi pdiBase = item.Key; IList <Pdi> duplicados = item.Value; List <Pdi> pdis = new List <Pdi> { pdiBase }; pdis.AddRange(duplicados); // Crea un grupo para cada conjunto de duplicados. ListViewGroup grupo = new ListViewGroup(pdiBase.Nombre) { Tag = pdis }; miLista.Groups.Add(grupo); // Añade todos los PDIs. miLista.Items.Add(CreaItemDeLista(pdiBase, grupo, 0)); foreach (Pdi duplicado in duplicados) { double distancia = Coordenadas.DistanciaEnMetros(pdiBase.Coordenadas, duplicado.Coordenadas); miLista.Items.Add(CreaItemDeLista(duplicado, grupo, distancia)); } } miLista.ResumeLayout(false); // Actualiza el Número de PDIs a Eliminar. ActualizaNúmeroDePdisAEliminar(); }
/// <summary> /// Process one road. /// </summary> /// <param name="theRoad">The road.</param> /// <returns>The number of changes made to the element.</returns> protected override int ProcesaElemento(Vía theRoad) { int numberOfChanges = 0; string targetName = null; double minimumDistance = double.NaN; // For each road we look for a match. var currentName = theRoad.Nombre.Trim(); // We only consider non-empty names. if (!string.IsNullOrEmpty(currentName)) { foreach (ElementoDelMapa element in mySourceElements) { var sourceRoad = element as Vía; if (sourceRoad != null) { // The first match is the road name. var sourceName = sourceRoad.Nombre.Trim(); if (!string.IsNullOrEmpty(sourceName)) { if (sourceName.StartsWith(currentName, StringComparison.InvariantCultureIgnoreCase)) { // We may have a match. // Now we look for coordinates. var start = theRoad.Coordenadas[0]; var sourceStart = sourceRoad.Coordenadas[0]; double distance = Coordenadas.DistanciaEnMetros(start, sourceStart); if ((distance < MinimumDistanceInMeters) && !(distance >= minimumDistance)) { minimumDistance = distance; targetName = sourceName; } } } } } } if (targetName != null) { bool cambió = theRoad.ActualizaNombre( targetName, string.Format(Recursos.M108, string.Format("{0:0.0 m.}", minimumDistance))); if (cambió) { ++numberOfChanges; } } return(numberOfChanges); }
private int BuscaPosibleExtremosDesconectados( Vía laVía, Vía laVíaDestino) { int númeroDeProblemasDetectados = 0; // Necesitamos al menos dos nodos. Coordenadas[] losNodos = laVía.Coordenadas; int númeroDeNodos = losNodos.Length; if (númeroDeNodos >= 2) { #region Crea los nodos extremos. int índiceUltimoNodo = númeroDeNodos - 1; List <int> índicesNodosExtremos = new List <int>(); // Nos saltamos el nodo si éste tiene el atributo de índice desconectado. string atributoNodoDesconectado = AtributoNodoDesconectado + ",0"; if (!laVía.TieneAtributo(atributoNodoDesconectado)) { índicesNodosExtremos.Add(0); } atributoNodoDesconectado = AtributoNodoDesconectado + ',' + índiceUltimoNodo.ToString(CultureInfo.InvariantCulture); if (!laVía.TieneAtributo(atributoNodoDesconectado)) { índicesNodosExtremos.Add(índiceUltimoNodo); } #endregion // Busca la distancia mínima a los nodos de la vía. foreach (int índiceNodo in índicesNodosExtremos) { Coordenadas nodo = laVía.Coordenadas[índiceNodo]; double distanciaNodoMasCercano = double.MaxValue; int índiceNodoMasCercano = 0; int númeroDeNodosDestino = laVíaDestino.Coordenadas.Length; for (int índiceNodoDestino = 0; índiceNodoDestino < númeroDeNodosDestino; ++índiceNodoDestino) { Coordenadas nodoDestino = laVíaDestino.Coordenadas[índiceNodoDestino]; // Nos saltamos este nodo si tiene las mismas coordenadas. bool tienenLasMismasCoordenadas = (nodo == nodoDestino); if (tienenLasMismasCoordenadas) { distanciaNodoMasCercano = 0; continue; } // Busca el nodo mas cercano. double distancia = Coordenadas.DistanciaEnMetros(nodo, nodoDestino); if (distancia < distanciaNodoMasCercano) { distanciaNodoMasCercano = distancia; índiceNodoMasCercano = índiceNodoDestino; } } // Si la distancia al nodo mas cercano es cero quiere decir que tiene las mismas // coordenadas. En este caso nos saltamos este nodo extremo porque // nodos con las mismas coordenadas son procesados en otro ciclo. if (distanciaNodoMasCercano == 0) { continue; } // Los nodos son posibles nodos desconectados si la distancia entre // ellos es menor que la distancia máxima de búsqueda. if (distanciaNodoMasCercano < DistanciaMáxima) { // Si la vía tiene algun otro nodo conectado al nodo destino // entonces nos saltamos este nodo. bool laVíaTieneOtroNodoConectadoAlNodoDestino = false; foreach (Coordenadas nodoDeLaVía in laVía.Coordenadas) { Coordenadas nodoMasCercano = laVíaDestino.Coordenadas[índiceNodoMasCercano]; if (nodoDeLaVía == nodoMasCercano) { laVíaTieneOtroNodoConectadoAlNodoDestino = true; break; } } if (!laVíaTieneOtroNodoConectadoAlNodoDestino) { string error = string.Format("E107: La distancia es menor que {0:0.0} m: {1:0.0} m.", DistanciaMáxima, distanciaNodoMasCercano); InformaciónNodoDesconectado posibleNodoDesconectado = new InformaciónNodoDesconectado( new Nodo(laVía, índiceNodo), new Nodo(laVíaDestino, índiceNodoMasCercano), distanciaNodoMasCercano, error); PosibleNodosDesconectados.Add(posibleNodoDesconectado); ++númeroDeProblemasDetectados; } } } } return(númeroDeProblemasDetectados); }
private void DibujaEscala() { // Calcula el largo del segmento de la escala en metros. // Para eso calculamos las coordenadas de los extremos del segmento // y con las coordenadas calculamos la distancia en metros. int bordeDeAbajoEnPixels = ClientRectangle.Bottom; Point origenDelSegmentoEnPixels = new Point(miOffsetDeEscalaEnPixels.X, bordeDeAbajoEnPixels - miOffsetDeEscalaEnPixels.Y); PointF origenDelSegmentoEnCoordenadas = PixelsACoordenadas(origenDelSegmentoEnPixels); Point finalDelSegmentoMínimoEnPixels = new Point(origenDelSegmentoEnPixels.X + miLargoDelSegmentoMínimoEnPixels, origenDelSegmentoEnPixels.Y); PointF finalDelSegmentoMínimoEnCoordenadas = PixelsACoordenadas(finalDelSegmentoMínimoEnPixels); miLargoDelSegmentoMínimoEnMetros = Coordenadas.DistanciaEnMetros(origenDelSegmentoEnCoordenadas, finalDelSegmentoMínimoEnCoordenadas); // Si el largo del segmento es zero entonces nos salimos. if (miLargoDelSegmentoMínimoEnMetros <= 0) { return; } // Descompone el largo del segmento mínimo en exponente y mantisa. int exponenteDelSegmentoMínimo = (int)Math.Log10(miLargoDelSegmentoMínimoEnMetros); double mantisaDelSegmentoMínimo = miLargoDelSegmentoMínimoEnMetros / Math.Pow(10, exponenteDelSegmentoMínimo); // Como queremos mostrar la escala en números enteros tenemos que hacer // que la mantisa de la escala sea el menor número entero que sea mayor // o igual que la mantisa del segmento mínimo. // Por ejemplo, si el largo del segmento mínimo es 93m, entonces el // exponente es 1 y la mantisa es 9,3 (93 = 9,3 * 10^1). Como en la // escala queremos mostar 100m en vez de 93m, entonces usamos una // mantisa de 10. int mantisaDeLaEscala = (int)Math.Ceiling(mantisaDelSegmentoMínimo); int largoDelSegmentoEnMetros = mantisaDeLaEscala * (int)Math.Pow(10, exponenteDelSegmentoMínimo); // Como la escala que vamos a mostrar puede ser mayor que la escala // del segmento mínimo (por ejemplo: 100m en vez de 93m), entonces // tenemos que ajustar el largo del segmento a dibujar. double factor = largoDelSegmentoEnMetros / miLargoDelSegmentoMínimoEnMetros; int intervaloEnPixels = (int)Math.Round(miLargoDelSegmentoMínimoEnPixels * factor); // Pone la unidad de la escala (metros o kilómetros). string unidad; int exponenteDeLaEscala; if (exponenteDelSegmentoMínimo < 3) { unidad = "m"; exponenteDeLaEscala = 0; } else { unidad = "km"; exponenteDeLaEscala = 3; } int largoDelSegmentoEnMetrosOKilómetros = (int)Math.Round(largoDelSegmentoEnMetros / Math.Pow(10, exponenteDeLaEscala)); #region Dibuja la Escala // Construye los puntos del segmento y los marcadores. const int largoMarcador = 5; Point marcadorIzquierdo = new Point(origenDelSegmentoEnPixels.X, origenDelSegmentoEnPixels.Y - largoMarcador); Point finalDelSegmento = new Point(origenDelSegmentoEnPixels.X + intervaloEnPixels, origenDelSegmentoEnPixels.Y); Point marcadorDerecho = new Point(origenDelSegmentoEnPixels.X + intervaloEnPixels, origenDelSegmentoEnPixels.Y - largoMarcador); Point[] líneas = new[] { marcadorIzquierdo, origenDelSegmentoEnPixels, finalDelSegmento, marcadorDerecho }; // Dibuja el segmento y los marcadores con un fondo para que // tenga un buen contraste. miGráficador.DrawLines(miLápizDeFondoParaEscala, líneas); miGráficador.DrawLines(miLápizParaEscala, líneas); // Dibuja el texto. string texto = largoDelSegmentoEnMetrosOKilómetros + " " + unidad; DibujaTextoConFondo(texto, origenDelSegmentoEnPixels.X + 2, origenDelSegmentoEnPixels.Y - 14, miLetraParaEscala, miPincelParaEscala, miPincelDeFondoParaEscala); #endregion }
/// <summary> /// Procesa un PDI. /// </summary> /// <param name="elPdi">El PDI.</param> /// <returns>El número de problemas detectados al procesar el elemento.</returns> protected override int ProcesaElemento(Pdi elPdi) { int númeroDeProblemasDetectados = 0; // Retorna si el PDI ya ha sido identificado como duplicado. if (misPdisDuplicados.Contains(elPdi)) { return(númeroDeProblemasDetectados); } List <Pdi> duplicados = new List <Pdi>(); // Busca en todos los PDIs desde la posición n + 1 que // no estén eliminados. for (int i = IndiceDeElementoProcesándose + 1; i < NúmeroDeElementos; ++i) { Pdi posiblePdiDuplicado = this[i]; if (!posiblePdiDuplicado.FuéEliminado) { // Si el PDI es idéntico entonces se puede borrar de una. if (posiblePdiDuplicado.TieneLaMismaInformación(elPdi)) { posiblePdiDuplicado.Elimina(string.Format(Properties.Recursos.M006, elPdi.Número)); misPdisDuplicados.Add(posiblePdiDuplicado); ++miNúmeroDeElementosEliminados; } else { // Si el PDI no es idéntico entonces puede ser duplicado si: // - El tipo principal es el mismo, y // - La distancia es cercana, y // - El nombre es igual, o // - Uno es las siglas del otro, o // - El nombre es parecido. if ((elPdi.Tipo != null) && (posiblePdiDuplicado.Tipo != null) && (((Tipo)elPdi.Tipo).TipoPrincipal == ((Tipo)posiblePdiDuplicado.Tipo).TipoPrincipal)) { double distanciaEnMetros = Coordenadas.DistanciaEnMetros(elPdi.Coordenadas, posiblePdiDuplicado.Coordenadas); if (distanciaEnMetros <= miDistanciaMáxima) { bool esDuplicado = false; // Nombre es igual? if (elPdi.Nombre == posiblePdiDuplicado.Nombre) { esDuplicado = true; } // El PDI es las siglas del posible duplicado? else if (PuedeSerSiglas(elPdi.Nombre)) { string siglasPosibleDuplicado = ObtieneSiglas(posiblePdiDuplicado.Nombre); if (elPdi.Nombre == siglasPosibleDuplicado) { esDuplicado = true; } } // El posible duplicado es las siglas del PDI? else if (PuedeSerSiglas(posiblePdiDuplicado.Nombre)) { string siglasPdi = ObtieneSiglas(elPdi.Nombre); if (siglasPdi == posiblePdiDuplicado.Nombre) { esDuplicado = true; } } // El nombre es parecido? else { TstDictionary diccionario = new TstDictionary { { elPdi.Nombre, null } }; ICollection resultados = diccionario.NearNeighbors(posiblePdiDuplicado.Nombre, miDistanciaHamming); // Como solo estamos comparando el nombre del PDI con el nombre del // posible duplicado, entonces al tener un solo resultado significa // que son parecidos. if (resultados.Count > 0) { esDuplicado = true; } } if (esDuplicado) { duplicados.Add(posiblePdiDuplicado); misPdisDuplicados.Add(posiblePdiDuplicado); } } } } } } if (duplicados.Count > 0) { misGruposDeDuplicados.Add(elPdi, duplicados); ++númeroDeProblemasDetectados; } return(númeroDeProblemasDetectados); }