Exemplo n.º 1
0
int ON_Brep::SplitEdgeAtParameters(
  int edge_index,
  int edge_t_count,
  const double* edge_t
  )
{
  // Default kink_tol_radians MUST BE ON_PI/180.0.
  //
  // The default kink tol must be kept in sync with the default for 
  // TL_Brep::SplitKinkyFace() and ON_Brep::SplitKinkyFace().
  // See comments in TL_Brep::SplitKinkyFace() for more details.

  if (0 == edge_t_count)
    return 0;
  if (0 == edge_t)
    return 0;
  if (edge_index < 0 || edge_index >= m_E.Count()) 
    return 0;
  ON_BrepEdge& E = m_E[edge_index];
  if (E.m_c3i < 0) 
    return 0;
  ON_Curve* curve = m_C3[E.m_c3i];
  if (!curve) 
    return 0;

  ON_Interval Edomain;
  if ( !E.GetDomain(&Edomain.m_t[0],&Edomain.m_t[1]) )
    return 0;
  if ( !Edomain.IsIncreasing() )
    return 0;

  // get a list of unique and valid splitting parameters
  ON_SimpleArray<double> split_t(edge_t_count);
  {
    for (int i = 0; i < edge_t_count; i++)
    {
      double e = edge_t[i];
      if ( !ON_IsValid(e) )
      {
        ON_ERROR("Invalid edge_t[] value");
        continue;
      }
      if ( e <= Edomain.m_t[0] )
      {
        ON_ERROR("edge_t[] <= start of edge domain");
        continue;
      }
      if ( e >= Edomain.m_t[1] )
      {
        ON_ERROR("edge_t[] >= end of edge domain");
        continue;
      }
      split_t.Append(e);
    }
    if ( split_t.Count() > 1 )
    {
      // sort split_t[] and remove duplicates
      ON_SortDoubleArray( ON::heap_sort, split_t.Array(), split_t.Count() );
      int count = 1;
      for ( int i = 1; i < split_t.Count(); i++ )
      {
        if ( split_t[i] > split_t[count-1] )
        {
          if ( i > count )
            split_t[count] = split_t[i];
          count++;
        }
      }
      split_t.SetCount(count);
    }
  }

  if (split_t.Count() <= 0) 
    return 0;

  // Reverse split_t[] so the starting segment of the original
  // edge m_E[edge_index] is the one at m_E[edge_index].
  split_t.Reverse();

  ON_Curve* new_curve = TuneupSplitteeHelper(m_E[edge_index].ProxyCurve());
  if ( 0 != new_curve )
  {
    m_E[edge_index].m_c3i = AddEdgeCurve(new_curve);
    m_E[edge_index].SetProxyCurve(new_curve);
    new_curve = 0;
  }

  int eti, ti;
  int successful_split_count = 0;
  for (int i=0; i<split_t.Count(); i++)
  {
    double t0, t1;
    m_E[edge_index].GetDomain(&t0, &t1);
    if (t1 - t0 < 10.0*ON_ZERO_TOLERANCE) 
      break;

    //6 Dec 2002 Dale Lear:
    //   I added the relative edge_split_s and trm_split_s tests to detect
    //   attempts to trim a nano-gnats-wisker off the end of a trim.
    double edge_split_s = ON_Interval(t0,t1).NormalizedParameterAt(split_t[i]);
    double trim_split_s = 0.5;

    if (split_t[i] - t0 <= ON_ZERO_TOLERANCE || edge_split_s <= ON_SQRT_EPSILON )
    {
      // this split is not possible
      continue;
    }
    
    if (t1 - split_t[i] <= ON_ZERO_TOLERANCE || edge_split_s >= 1.0-ON_SQRT_EPSILON)
    {
      // this split is not possible
      continue;
    }

    // trim_t[] = corresponding trim parameters
    ON_SimpleArray<double> trim_t(m_E[edge_index].m_ti.Count());

    for ( eti = 0; eti < m_E[edge_index].m_ti.Count(); eti++)
    {
      ti = m_E[edge_index].m_ti[eti];
      if ( ti < 0 || ti >= m_T.Count() )
        continue;
      ON_BrepTrim& trim = m_T[ti];
      if ( 0 == i )
      {
        // On the first split, make sure the trim curve is up to snuff.
        new_curve = TuneupSplitteeHelper(trim.ProxyCurve());
        if (new_curve)
        {
          trim.m_c2i = AddTrimCurve(new_curve);
          trim.SetProxyCurve(new_curve);
          new_curve = 0;
        }
      }
      double t = ON_UNSET_VALUE;
      if (!GetTrimParameter(ti, split_t[i], &t) || !ON_IsValid(t))
        break;
      trim_t.Append(t);
      const ON_Interval trim_domain = trim.Domain();
      trim_split_s = trim_domain.NormalizedParameterAt(t);
      if ( trim_split_s <= ON_SQRT_EPSILON || t - trim_domain[0] <= ON_ZERO_TOLERANCE )
        break;

      if ( trim_split_s >= 1.0-ON_SQRT_EPSILON || trim_domain[1] - t <= ON_ZERO_TOLERANCE )
        break;
    }

    if ( trim_t.Count() != m_E[edge_index].m_ti.Count() )
      continue;

    if (!SplitEdge(edge_index, split_t[i], trim_t))
    {
      continue;
    }

    // SplitEdge generally adjusts proxy domains instead
    // of trimming the orginal curve. These DuplicateCurve()
    // calls make a new curve whose domain exactly matches
    // the edge.
    for ( int epart = 0; epart < 2; epart++ )
    {
      ON_BrepEdge* newE = (0 == epart) ? &m_E[edge_index] : m_E.Last();
      if ( 0 == newE )
        continue;
      new_curve = TuneupEdgeOrTrimRealCurve(*newE,true);
      if (new_curve)
      {
        newE->m_c3i = AddEdgeCurve(new_curve);
        newE->SetProxyCurve(new_curve);
      }
      for ( eti = 0; eti < newE->m_ti.Count(); eti++ )
      {
        ti = newE->m_ti[eti];
        if ( ti < 0 || ti >= m_T.Count() )
          continue;
        ON_BrepTrim& trim = m_T[ti];
        new_curve = TuneupEdgeOrTrimRealCurve(trim,false);
        if (new_curve)
        {
          trim.m_c2i = AddTrimCurve(new_curve);
          trim.SetProxyCurve(new_curve);
        }
      }
    }

    successful_split_count++;
  }

  return successful_split_count;
}