private CPUFieldLineModel SeedsToNewModels(Vector4 seed)
    {
        var gameObj = new GameObject("FieldLineModel");

        gameObj.transform.SetParent(transform);
        CPUFieldLineModel newModel = gameObj.AddComponent <CPUFieldLineModel>();

        newModel.Initialize(CPUFieldLineManager.Instance.settings.calculationSettings,
                            CPUFieldLineManager.Instance.FieldType,
                            CPUFieldLineManager.Instance.settings.appearanceSettings,
                            seed.w > 0 ? IntegrationDirection.FromNegative : IntegrationDirection.FromPositive);

        return(newModel);
    }
//    /// <summary>
//    /// Planar mode. Calculate each point of each field line associated with this geometry and stage for drawing.
//    /// Removed because the do-calculation command for each geometry should be independent of draw space setting.
//    /// </summary>
//    public virtual void CalculatePlanarFieldLines(int charge, Plane plane)
//    {
//        Vector4[] seeds = FieldLineSeedsInPlane(charge, plane);
//        AssociateModelsWithSeeds(seeds);
//        for (int i = 0; i < fieldLineModels.Count; i++)
//        {
//            CPUFieldLineModel model = fieldLineModels[i];
//            Vector4 seed = seeds[i];
//            Vector3 position = new Vector3(seed.x, seed.y, seed.z);
//            CPUFieldLineModel.IntegrationDirection integrationDirection = seed.w > 0
//                ? CPUFieldLineModel.IntegrationDirection.DownField
//                : CPUFieldLineModel.IntegrationDirection.UpField;
//            model.SetPositionAndIntegrationDirection(position, integrationDirection);
//            model.ExecuteCalculation();
//        }
//    }
//    /// <summary>
//    /// Volumetric mode. Calculate each point of each field line associated with this geometry and stage for drawing.
//    /// </summary>
//    public abstract void CalculateVolumetricFieldLines(int charge);

    public virtual void CalculateFieldLines()
    {
        AssociateModelsWithSeeds(storedSeeds);
        for (int i = 0; i < fieldLineModels.Count; i++)
        {
            CPUFieldLineModel    model                = fieldLineModels[i];
            Vector4              seed                 = storedSeeds[i];
            Vector3              position             = new Vector3(seed.x, seed.y, seed.z);
            IntegrationDirection integrationDirection = seed.w > 0
                ? IntegrationDirection.FromNegative
                : IntegrationDirection.FromPositive;
            model.SetPositionAndIntegrationDirection(position, integrationDirection);
            model.ExecuteCalculation();
        }
    }
    // We're reporting field line terminations directly to CPUFieldLineManager for the moment, so don't need this method.
//    public void ReportLandedFieldLine(CPUFieldLineModel model)
//    {
//        _landedFieldLines.Add(model);
//    }

    private List <CPUFieldLineModel> SeedsToNewModels(Vector4[] seeds)
    {
        List <CPUFieldLineModel> outList = new List <CPUFieldLineModel>();

        foreach (Vector4 seed in seeds)
        {
            var gameObj = new GameObject("FieldLineModel");
            gameObj.transform.SetParent(transform);
            CPUFieldLineModel newModel = gameObj.AddComponent <CPUFieldLineModel>();
            newModel.Initialize(CPUFieldLineManager.Instance.settings.calculationSettings,
                                CPUFieldLineManager.Instance.FieldType,
                                CPUFieldLineManager.Instance.settings.appearanceSettings,
                                seed.w > 0 ? IntegrationDirection.FromNegative : IntegrationDirection.FromPositive);
            // Didn't seem to be working; changed Append to Add
            outList.Add(newModel);
        }

        return(outList);
    }
    public void ReportFieldLineTermination(CPUFieldLineModel model, CPUFieldLineModel.TerminationReason termReason)
    {
        // Determine whether the field line could have landed on another geometry
        // It is not clear whether this is a sufficient check.
        if (termReason != CPUFieldLineModel.TerminationReason.BackTolerance)
        {
            return;
        }

        // TODO skip cases where e.g. the field line is positive-sourced and the geometry is associated with a positive charge.
        FieldLineTerminalGeometry geometryTerminatedUpon = null;

        foreach (FieldLineTerminalGeometry geometry in terminalGeometries)
        {
            if (geometry.IsPointWithinGeometry(model.LastPoint))
            {
                geometryTerminatedUpon = geometry;
                break;
            }
        }
        // If we didn't find a geometry the field line landed on, that's weird; throw a warning and return
        if (!geometryTerminatedUpon)
        {
            Debug.LogWarning("This field line thinks it terminated on a geometry, but its endpoint is not contained within any terminal geometry. This shouldn't happen.", model);
        }
        else
        {
            // If a geometry this field line landed on was found, add the field line to the dict.

            // Check to see if this geometry is already in the dict.
            // If it isn't, add it as a key with an empty list of CPUFieldLineModels as its value.
            if (!_landedLines.ContainsKey(geometryTerminatedUpon))
            {
                _landedLines.Add(geometryTerminatedUpon, new List <CPUFieldLineModel>());
            }
            // Add the landed field line model to the geometry's list of field line models.
            _landedLines[geometryTerminatedUpon].Add(model);
        }
    }
    public override Vector4[] RejectSeedsForExistingFieldLines(List <CPUFieldLineModel> existingFieldLines)
    {
        CPUFieldLineModel firstLandedLine = existingFieldLines[0];
        // Get the direction of approach of the first field line to land, and rotate our geometry to match

        Vector3 firstLandedLineIncomingDirection = firstLandedLine.LastDirection;
        Vector3 firstLandedLineLastPoint         = firstLandedLine.LastPoint;

        List <Vector4> seedsToRemove = new List <Vector4>();

        foreach (CPUFieldLineModel landedLine in existingFieldLines)
        {
            foreach (Vector4 seed in storedSeeds)
            {
                if (LandedFieldLineIsNearSeed(landedLine.LastDirection, seed))
                {
                    seedsToRemove.Add(seed);
                }
            }
        }

        return(seedsToRemove.ToArray());
    }