public static SamplingEntry Divide(ref SamplingEntry oldEntry, double prevUpperLimit, double prevCumulativeWeight, double weightMult, double newUpperLimit) { SamplingEntry newEntry = new SamplingEntry(); newEntry.UpperLimit = newUpperLimit; double newWidth = newUpperLimit - prevUpperLimit; double oldWidth = oldEntry.UpperLimit - newUpperLimit; double t = newWidth / (newWidth + oldWidth); newEntry.Full = oldEntry.Full; if (oldEntry.Sampler != null) { newEntry.Sampler = new IntervalSampler(oldEntry.Sampler, t, clone: false); // Will fix weights of the old sampler as well newEntry.CumulativeWeight = prevCumulativeWeight + newEntry.Sampler.TotalWeight; oldEntry.CumulativeWeight = newEntry.CumulativeWeight + oldEntry.Sampler.TotalWeight; } else { newEntry.Sampler = null; if (oldEntry.Full) { newEntry.CumulativeWeight = oldEntry.CumulativeWeight = prevCumulativeWeight; } else { newEntry.CumulativeWeight = prevCumulativeWeight + weightMult * newWidth; oldEntry.CumulativeWeight = newEntry.CumulativeWeight + weightMult * oldWidth; } } return newEntry; }
public static SamplingEntry Divide(ref SamplingEntry oldEntry, double prevUpperLimit, double prevCumulativeWeight, double weightMult, double newUpperLimit) { SamplingEntry newEntry = new SamplingEntry(); newEntry.UpperLimit = newUpperLimit; double newWidth = newUpperLimit - prevUpperLimit; double oldWidth = oldEntry.UpperLimit - newUpperLimit; double t = newWidth / (newWidth + oldWidth); newEntry.Full = oldEntry.Full; if (oldEntry.Sampler != null) { newEntry.Sampler = new IntervalSampler(oldEntry.Sampler, t, clone: false); // Will fix weights of the old sampler as well newEntry.CumulativeWeight = prevCumulativeWeight + newEntry.Sampler.TotalWeight; oldEntry.CumulativeWeight = newEntry.CumulativeWeight + oldEntry.Sampler.TotalWeight; } else { newEntry.Sampler = null; if (oldEntry.Full) { newEntry.CumulativeWeight = oldEntry.CumulativeWeight = prevCumulativeWeight; } else { newEntry.CumulativeWeight = prevCumulativeWeight + weightMult * newWidth; oldEntry.CumulativeWeight = newEntry.CumulativeWeight + weightMult * oldWidth; } } return(newEntry); }
public SamplingEntry(SamplingEntry other) { UpperLimit = other.UpperLimit; CumulativeWeight = other.CumulativeWeight; Full = other.Full; if (other.Sampler == null) { Sampler = null; } else { Sampler = new IntervalSampler(other.Sampler, 1.0, clone: true); } }
private void Multiply(double t) { m_weightMult *= t; m_totalWeight *= t; for (int i = 0; i < m_entries.Count; ++i) { SamplingEntry entry = m_entries[i]; entry.CumulativeWeight *= t; m_entries[i] = entry; if (entry.Sampler != null) { entry.Sampler.Multiply(t); } } }
private IntervalSampler(IntervalSampler other, double t, bool clone) { m_min = other.m_min; m_max = other.m_max; m_axis = other.m_axis; m_weightMult = other.m_weightMult; m_totalWeight = other.m_totalWeight; m_entries = new List <SamplingEntry>(other.m_entries); for (int i = 0; i < other.m_entries.Count; ++i) { m_entries[i] = new SamplingEntry(other.m_entries[i]); } Multiply(t); // If we are not cloning, we are splitting, so we have to multiply the remnant as well if (!clone) { other.Multiply(1.0 - t); } }
private IntervalSampler(IntervalSampler other, double t, bool clone) { m_min = other.m_min; m_max = other.m_max; m_axis = other.m_axis; m_weightMult = other.m_weightMult; m_totalWeight = other.m_totalWeight; m_entries = new List<SamplingEntry>(other.m_entries); for (int i = 0; i < other.m_entries.Count; ++i) { m_entries[i] = new SamplingEntry(other.m_entries[i]); } Multiply(t); // If we are not cloning, we are splitting, so we have to multiply the remnant as well if (!clone) { other.Multiply(1.0 - t); } }
public void Subtract(ref BoundingBoxD originalBox, ref BoundingBoxD bb) { double min, max; SelectMinMax(ref bb, m_axis, out min, out max); bool minInserted = false; double prevLimit = m_min; double cumul = 0.0; for (int i = 0; i < m_entries.Count; ++i) { SamplingEntry entry = m_entries[i]; if (!minInserted) { if (entry.UpperLimit >= min) { if (entry.UpperLimit == min) { minInserted = true; } else // (entry.UpperLimit > min) { if (prevLimit == min) { minInserted = true; i--; continue; } minInserted = true; SamplingEntry insertedEntry = SamplingEntry.Divide(ref entry, prevLimit, cumul, m_weightMult, min); m_entries[i] = entry; m_entries.Insert(i, insertedEntry); entry = insertedEntry; } } } else { if (prevLimit < max) { if (entry.UpperLimit > max) { SamplingEntry insertedEntry = SamplingEntry.Divide(ref entry, prevLimit, cumul, m_weightMult, max); m_entries[i] = entry; m_entries.Insert(i, insertedEntry); entry = insertedEntry; } if (entry.UpperLimit <= max) { if (entry.Sampler == null) { if (m_axis == Base6Directions.Axis.ForwardBackward) { entry.Full = true; entry.CumulativeWeight = cumul; } else { if (entry.Full == false) // Full entries can be kept as they are { Base6Directions.Axis nextAxis = m_axis == Base6Directions.Axis.LeftRight ? Base6Directions.Axis.UpDown : Base6Directions.Axis.ForwardBackward; double min2, max2; SelectMinMax(ref originalBox, nextAxis, out min2, out max2); double range = m_max - m_min; double volume = m_weightMult * range; double relativeWidth = (entry.UpperLimit - prevLimit) / range; double newRange = max2 - min2; entry.Sampler = new IntervalSampler(min2, max2, (volume * relativeWidth) / newRange, nextAxis); } } } if (entry.Sampler != null) { entry.Sampler.Subtract(ref originalBox, ref bb); entry.CumulativeWeight = cumul + entry.Sampler.TotalWeight; } m_entries[i] = entry; } } else { if (entry.Sampler == null) { if (entry.Full) { entry.CumulativeWeight = cumul; } else { entry.CumulativeWeight = cumul + (entry.UpperLimit - prevLimit) * m_weightMult; } } else { entry.CumulativeWeight = cumul + entry.Sampler.TotalWeight; } m_entries[i] = entry; } } prevLimit = entry.UpperLimit; cumul = entry.CumulativeWeight; } m_totalWeight = cumul; }