Exemplo n.º 1
0
        public Vector2 GetPinPairDir(SceneObjects.Part src, int iPin1, int iPin2)
        {
            var pin1 = Root.Scene.Pins[src.FirstPin + iPin1].Location;
            var pin2 = Root.Scene.Pins[src.FirstPin + iPin2].Location;

            return(Vector2.Max(pin1, pin2) - Vector2.Min(pin1, pin2));
        }
Exemplo n.º 2
0
        public bool CheckPinRow(SceneObjects.Part part, int first, int count, int stride = 1)
        {
            const double distThreshold = 1; // 5 mil?
            //const double stepThreshold = 0.025; // 1.43 deg
            //const double finalThreshold = 0.025; // 1.43 deg
            //var dir = Vector2.Origin;
            //var error = 0.0;
            //for (int i = part.FirstPin+first+1; i<part.FirstPin+first+count; i++)
            //{
            //    var newDir = Root.Scene.Pins[i].Location-Root.Scene.Pins[i-1].Location;
            //    var newAng = newDir.RelativeAngle(dir);
            //    error += newAng;
            //}
            var iFirst   = part.FirstPin + first;
            var firstPin = Root.Scene.Pins[iFirst].Location;
            var lastPin  = Root.Scene.Pins[iFirst + (count - 1) * stride].Location;
            var maxDst   = 0.0;

            for (int i = iFirst + stride; i < iFirst + (count - 1) * stride; i += stride)
            {
                var pin    = Root.Scene.Pins[i].Location;
                var newDst = pin.DistanceToSegment(firstPin, lastPin);
                if (newDst > maxDst)
                {
                    maxDst = newDst;
                }
            }
            if (maxDst > distThreshold)
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 3
0
        private Box2 CalculatePartBBox(SceneObjects.Part src)
        {
            var bbox = Box2.Empty;

            for (int i = src.FirstPin; i < src.FirstPin + src.PinCount; i++)
            {
                bbox.Merge(Root.Scene.Pins[i].Location);
            }
            var c = '\0';

            if (src.Name.Length >= 2)
            {
                c = src.Name[0];
            }
            var growR = 1.0;

            switch (c)
            {
            case 'U':
                growR = 0.0;
                break;
            }
            if (growR > 0) // outer box (+radius)
            {
                bbox.Grow(Root.Scene.Options.PinBoxRadius * growR);
            }
            return(bbox);
        }
Exemplo n.º 4
0
        public double CalculatePinPairAngle(SceneObjects.Part src, int iPin1, int iPin2)
        {
            var dir = GetPinPairDir(src, iPin1, iPin2);

            if (dir.SqrLength < 0.001)
            {
                return(double.NaN);
            }
            return(dir.OriginAngle());
        }
Exemplo n.º 5
0
 private bool DetectF(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
 {
     if (src.PinCount < 2)
     {
         angle = 0;
         return(false);
     }
     angle = CalculatePinPairAngle(src, 0, 1);
     return(true);
 }
Exemplo n.º 6
0
        // If the order is not known in advance, we need a slightly more complicated check:
        private bool CheckPinRect(SceneObjects.Part src, double threshold)
        {
            var a = Root.Scene.Pins[src.FirstPin + 0].Location;
            var b = Root.Scene.Pins[src.FirstPin + 1].Location;
            var c = Root.Scene.Pins[src.FirstPin + 2].Location;
            var d = Root.Scene.Pins[src.FirstPin + 3].Location;

            return(IsRectangle(a, b, c, d, threshold) ||
                   IsRectangle(b, c, a, d, threshold) ||
                   IsRectangle(c, a, b, d, threshold));
        }
Exemplo n.º 7
0
 private bool DetectXW(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
 {
     angle = 0;
     // XW-specific
     aspect = 0;
     growR  = 0.5;
     switch (src.PinCount)
     {
     case 2:
         angle = CalculatePinPairAngle(src, 0, 1);
         return(true);
     }
     return(false);
 }
Exemplo n.º 8
0
 private bool DetectY(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
 {
     if (src.PinCount < 2)
     {
         angle = 0;
         return(false);
     }
     if (src.PinCount > 2) // long packages have >2 pins
     {
         aspect = 0;
     }
     angle = CalculatePinPairAngle(src, 0, 1);
     return(true);
 }
Exemplo n.º 9
0
        private void AdjustPart(SceneObjects.Part src, ref OBB obb,
                                ref double aspect, ref double growR)
        {
            var match       = false;
            var originAngle = aligner.CalculatePartShape(src, ref aspect, ref growR, out match);

            if (match)
            {
                obb.Turn = originAngle;
                return;
            }
            if (!aligner.Check90degAlignment(originAngle))
            {
                obb.Turn = aligner.AdjustPartAngle(originAngle, true);
            }
        }
Exemplo n.º 10
0
        private bool CheckDualRow(SceneObjects.Part src, ref double angle,
                                  int r1a, int r1b, int r2a, int r2b)
        {
            var d1 = GetPinPairDir(src, r1a, r1b);
            var d2 = GetPinPairDir(src, r2a, r2b);

            if (d1 == Vector2.Origin || d2 == Vector2.Origin)
            {
                return(false);
            }
            if (d1.CrossingAngle(d2) < ParallelRowThreshold)
            {
                angle = d1.OriginAngle();
                return(true);
            }
            return(false);
        }
Exemplo n.º 11
0
        private bool DetectR(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
        {
            angle = 0;
            switch (src.PinCount)
            {
            case 2:
                angle = CalculatePinPairAngle(src, 0, 1);
                return(true);

            case 4:
                aspect = -0.6; // force aspect
                if (CheckPinRowOI(src, 0, 4))
                {
                    var d34 = GetPinPairDir(src, 2, 3).Length;
                    var d13 = GetPinPairDir(src, 0, 2).Length;
                    if (d34 < d13)
                    {
                        var f = d13 / d34;
                        if (f < 3.5 && !(1.3 < f && f < 1.7))
                        {
                            aspect = -1 / 0.6;
                        }
                    }
                    angle = CalculatePinPairAngle(src, 0, 3);
                    return(true);
                }
                // check this shape:

                /*
                 |      * |
                 | *      |
                 | *      |
                 |      * |
                 */
                if (CheckPinRect(src, 0.02))
                {
                    angle = CalculatePinPairAngle(src, 0, 1);
                    return(true);
                }
                angle = 0;
                return(true);
            }
            return(false);
        }
Exemplo n.º 12
0
 private bool DetectC(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
 {
     if (src.PinCount < 2)
     {
         angle = 0;
         return(false);
     }
     angle = CalculatePinPairAngle(src, 0, 1);
     if (src.PinCount == 2)
     {
         var d = GetPinPairDir(src, 0, 1).Length;
         if (163 <= d && d <= 164 ||
             202 <= d && d <= 203 ||
             137 <= d && d <= 138 ||
             d == 210)
         {
             src.DrawAsCircle = true;
         }
     }
     return(true);
 }
Exemplo n.º 13
0
        public double CalculatePartMinShape(SceneObjects.Part src,
                                            ref double aspect, ref double growR, out bool match)
        {
            match = true;
            if (src.PinCount <= 1)
            {
                return(0);
            }
            if (src.PinCount == 2)
            {
                var pin1 = Root.Scene.Pins[src.FirstPin + 0].Location;
                var pin2 = Root.Scene.Pins[src.FirstPin + 1].Location;
                var dir  = Vector2.Max(pin1, pin2) - Vector2.Min(pin1, pin2);
                if (dir.SqrLength < 0.001)
                {
                    return(0);
                }
                return(dir.OriginAngle());
            }
            var verts = new List <Vector2>(src.PinCount);

            for (int i = src.FirstPin; i < src.FirstPin + src.PinCount; i++)
            {
                var nv = Root.Scene.Pins[i].Location;
                if (verts.Count == 0)
                {
                    verts.Add(nv);
                    continue;
                }
                if (verts[verts.Count - 1] != nv)
                {
                    verts.Add(nv);
                }
            }
            var obb = MinimalOBB.Calculate(verts);

            return(obb.Turn);
        }
Exemplo n.º 14
0
        //private void FindPinLine(SceneObjects.Part src, out int pinCount, out double angle)
        //{
        //    var firstPin = src.FirstPin;
        //    var endPin = src.FirstPin+src.PinCount;
        //    int[] strides = {1, 4};
        //    pinCount = 0;
        //    angle = 0;
        //}

        // XXX: make variant of CheckPinRow that would find row length

        // order-independent version
        public bool CheckPinRowOI(SceneObjects.Part part, int first, int count, int stride = 1)
        {
            const double distThreshold = 1;
            var          iFirst        = part.FirstPin + first;
            var          firstPin      = Root.Scene.Pins[iFirst].Location;
            var          lastPin       = Root.Scene.Pins[iFirst + (count - 1) * stride].Location;
            var          maxDst        = 0.0;

            for (int i = iFirst + stride; i < iFirst + (count - 1) * stride; i += stride)
            {
                var pin    = Root.Scene.Pins[i].Location;
                var newDst = pin.DistanceToLine(firstPin, lastPin);
                if (newDst > maxDst)
                {
                    maxDst = newDst;
                }
            }
            if (maxDst > distThreshold)
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 15
0
        private bool DetectQ(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
        {
            if (src.PinCount < 2)
            {
                angle = 0;
                return(false);
            }
            angle = 0;
            switch (src.PinCount)
            {
            case 3:
                //if (!CheckPinRow(src, 0, 3))
                //    aspect = -1/aspect;
                // XXX: 3-pin Q/D parts should have rotated standard aspect
                // (and size based on max dimension instead of min)
            {
                var d12 = GetPinPairDir(src, 0, 1).Length;
                var d23 = GetPinPairDir(src, 1, 2).Length;
                var d13 = GetPinPairDir(src, 0, 2).Length;
                if (d12 < d23 && d12 < d13)
                {
                    angle = CalculatePinPairAngle(src, 0, 1);
                    return(true);
                }
                if (d23 < d12 && d23 < d13)
                {
                    angle = CalculatePinPairAngle(src, 1, 2);
                    return(true);
                }
                if (d13 < d23 && d13 < d12)
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                    return(true);
                }
            }
                return(true);

            case 4:
                if (CheckPinRow(src, 0, 3)) // 3+1
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                    return(true);
                }
                // XXX: 2+2
                break;

            case 5:
                if (CheckPinRow(src, 0, 3)) // 4+1, 3+2
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                    return(true);
                }
                break;

            case 6:
                if (CheckDualRow(src, ref angle, 0, 1, 4, 5))
                {
                    return(true);
                }
                if (CheckPinRow(src, 0, 3))
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                    return(true);
                }
                break;

            case 7:
                angle = CalculatePinPairAngle(src, 2, 3);
                return(true);

            case 8: // weird looking pin configuration (docked pentagons)
                if (CheckTripleRow(src, ref angle, 0, 2, 4, 6, 3, 7))
                {
                    return(true);
                }
                angle = CalculatePinPairAngle(src, 2, 3);
                return(true);

            case 9: // weird looking apple mosfet
                if (CheckPinRow(src, 4, 4))
                {
                    angle = CalculatePinPairAngle(src, 4, 7);
                    return(true);
                }
                if (CheckPinRow(src, 0, 3))
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                    return(true);
                }
                break;

            case 10: // diode assembly
                if (CheckDualRow(src, ref angle, 0, 1, 3, 4))
                {
                    return(true);
                }
                break;
            }
            if (src.PinCount > 10)
            {
                angle = CalculatePinPairAngle(src, 0, 1);
                return(true);
            }
            angle = 0.0;
            return(false);
        }
Exemplo n.º 16
0
        public double CalculatePartShape(SceneObjects.Part src,
                                         ref double aspect, ref double growR, out bool match)
        {
            var angle = 0.0;
            int i1    = 0;
            int i2    = 1;

            //growR = 1.0;
            //aspect = 1.0/2;
            switch (src.Name[0])
            {
            case 'C':
                if (src.Name.Length >= 3 && src.Name[1] == 'N' && char.IsNumber(src.Name[2])) // connector
                {
                    goto case 'J';
                }
                match = DetectC(src, ref aspect, ref growR, out angle);
                return(angle);

            case 'F':
                if (NameCharIsDigit(src, 1))
                {
                    match = DetectF(src, ref aspect, ref growR, out angle);
                    return(0);
                }
                if (NameCharIsLetter(src, 1, 'L') && NameCharIsDigit(src, 2))
                {
                    match = DetectL(src, ref aspect, ref growR, out angle);
                    return(angle);
                }
                break;

            case 'R':
                match = DetectR(src, ref aspect, ref growR, out angle);
                return(angle);

            case 'L':
                if (!NameCharIsDigit(src, 1))
                {
                    //goto case 'H';
                    goto case 'D';
                }
                //case 'H':
                match = DetectL(src, ref aspect, ref growR, out angle);
                return(angle);

            case 'D':
                if (src.Name.Length >= 3 && src.Name[1] == 'M' && char.IsNumber(src.Name[2]))
                {
                    goto case 'J';
                }
                goto case 'Q';

            case 'Q':
                match = DetectQ(src, ref aspect, ref growR, out angle);
                return(angle);

            case 'T':
                if (src.Name.Length >= 3 && src.Name[1] == 'C' && char.IsNumber(src.Name[2]))
                {
                    match = DetectTC(src, ref aspect, ref growR, out angle);
                    return(angle);
                }
                break;

            case 'U': // inner box (-radius or -0)
                match = DetectU(src, ref aspect, ref growR, out angle);
                return(angle);

            case 'J':
                match = DetectJ(src, ref aspect, ref growR, out angle);
                return(angle);

            case 'X':
                if (src.Name[1] == 'W')
                {
                    match = DetectXW(src, ref aspect, ref growR, out angle);
                    return(angle);
                }
                if (char.IsNumber(src.Name[1]))
                {
                    goto case 'Y';
                }
                break;

            case 'Y':
                match = DetectY(src, ref aspect, ref growR, out angle);
                return(angle);
            }
            aspect = 0;
            var result = 0.0;

            if (src.PinCount == 2)
            {
                result = CalculatePinPairAngle(src, i1, i2);
            }
            match = !double.IsNaN(result);
            return(result); // XXX: return 0
        }
Exemplo n.º 17
0
 private bool NameCharIsLetter(SceneObjects.Part src, int i, char chk)
 {
     return(src.Name.Length >= i + 1 && src.Name[i] == chk);
 }
Exemplo n.º 18
0
 private bool NameCharIsDigit(SceneObjects.Part src, int i)
 {
     return(src.Name.Length >= i + 1 && char.IsNumber(src.Name[i]));
 }
Exemplo n.º 19
0
        private bool LoadBoardView(string fileName, IBoardViewFile bdv)
        {
            if (!bdv.Load(fileName))
            {
                GC.Collect();
                GC.WaitForFullGCComplete();
                return(false);
            }
            SetCurrentFilename(Path.GetFileName(fileName));
            Root.Scene.Reset();
            GC.Collect();
            GC.WaitForFullGCComplete();
            if (bdv.InchUnits) // convert to mils
            {
                for (int i = 0; i < bdv.TopContour.Count; i++)
                {
                    bdv.TopContour[i] *= 1000;
                }
                for (int i = 0; i < bdv.BottomContour.Count; i++)
                {
                    bdv.BottomContour[i] *= 1000;
                }
                for (int i = 0; i < bdv.Nails.Count; i++)
                {
                    bdv.Nails[i].Location *= 1000;
                }
                for (int i = 0; i < bdv.Pins.Count; i++)
                {
                    bdv.Pins[i].Location *= 1000;
                }
                // ?
                //bdv.InchUnits = false;
            }
            Root.Scene.TopContour    = new SceneObjects.Contour(bdv.TopContour);
            Root.Scene.BottomContour = new SceneObjects.Contour(bdv.BottomContour);
            for (int i = 0; i < bdv.Parts.Count; i++)
            {
                var src = bdv.Parts[i];
                // process part pins and update bbox
                int flipScale = src.Side == BoardSide.Top || !bdv.FlipBottomY ? +1 : -1;
                var p         = new SceneObjects.Part();
                p.Side     = src.Side;
                p.FirstPin = src.FirstPin;
                p.PinCount = src.PinCount;
                p.Name     = src.Name;
                var pinSides = p.Side;
                for (int j = src.FirstPin; j < src.FirstPin + src.PinCount; j++)
                {
                    var loc = bdv.Pins[j].Location;
                    loc.Y *= flipScale;
                    bdv.Pins[j].Location = loc;
                    var pin = new SceneObjects.Pin(p);
                    pin.SelfIndex = j;
                    pin.Net       = bdv.Pins[j].Net;
                    pin.Name      = bdv.Pins[j].Name;
                    pin.Location  = bdv.Pins[j].Location;
                    pin.Side      = bdv.Pins[j].Side;
                    if (bdv.Pins[j].Inverse != null)
                    {
                        var invSrc = bdv.Pins[j].Inverse;
                        var ipin   = new SceneObjects.Pin(p);
                        ipin.SelfIndex = j;
                        ipin.Net       = invSrc.Net;
                        ipin.Name      = invSrc.Name;
                        ipin.Location  = invSrc.Location;
                        ipin.Side      = invSrc.Side;
                        ipin.Inverse   = pin;
                        pin.Inverse    = ipin;
                        pinSides      |= ipin.Side;
                        if (ipin.Side == BoardSide.Top)
                        {
                            Root.Scene.TopObjectSpace.Insert(ipin);
                        }
                        if (ipin.Side == BoardSide.Bottom)
                        {
                            Root.Scene.BottomObjectSpace.Insert(ipin);
                        }
                    }
                    pinSides |= pin.Side;
                    Root.Scene.Pins.Add(pin);
                    if (pin.Side == BoardSide.Top)
                    {
                        Root.Scene.TopObjectSpace.Insert(pin);
                    }
                    if (pin.Side == BoardSide.Bottom)
                    {
                        Root.Scene.BottomObjectSpace.Insert(pin);
                    }
                }
                p.HasThroughHolePins = pinSides != p.Side;
                p.Update(CalculatePartBBox(p), CalculatePartOBB(p));
                Root.Scene.Parts.Add(p);
            }
            // process through-hole pins
            int pinCount = Root.Scene.Pins.Count;

            for (int i = 0; i < pinCount; i++)
            {
                if (Root.Scene.Pins[i].Inverse != null)
                {
                    Root.Scene.Pins.Add(Root.Scene.Pins[i].Inverse);
                }
            }
            for (int i = 0; i < bdv.Nails.Count; i++)
            {
                var src  = bdv.Nails[i];
                var nail = new SceneObjects.Nail();
                nail.Side = src.Side;
                nail.Net  = src.Net;
                nail.Name = src.Name;
                int flipScale = src.Side == BoardSide.Top || !bdv.FlipBottomY ? +1 : -1;
                var loc       = src.Location;
                loc.Y        *= flipScale;
                src.Location  = loc;
                nail.Location = loc;
                Root.Scene.Nails.Add(nail);
                if (src.Side == BoardSide.Top)
                {
                    Root.Scene.TopObjectSpace.Insert(nail);
                }
                if (src.Side == BoardSide.Bottom)
                {
                    Root.Scene.BottomObjectSpace.Insert(nail);
                }
            }
            // ?
            //Root.Scene.Options.FlipBottomY = bdv.FlipBottomY;
            return(true);
        }
Exemplo n.º 20
0
        private bool DetectL(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
        {
            if (src.PinCount < 2)
            {
                angle = 0;
                return(false);
            }
            const double maxLongCoilSize  = 123;// 104;// 73; // mil?
            const double maxDiagCoilSize  = 175;
            const double bigCoilRotFactor = 9;
            const double cornerDx         = 0.5 / 1.41421356237; //0.5/Math.Sqrt(2);

            angle = 0;
            var dir     = GetPinPairDir(src, 0, 1);
            var diam    = dir.Length;
            var bigCoil = diam > maxLongCoilSize;

            if (bigCoil)
            {
                aspect = 1;
            }
            switch (src.PinCount)
            {
            case 2:
                if (bigCoil)
                {
                    var diagCoil = diam <= maxDiagCoilSize;
                    // XXX: either 0 or 45 degrees
                    var center = dir / 2;
                    var dx     = Math.Abs(center.X) / diam;
                    var dDiagX = Math.Abs(cornerDx - dx);
                    // same small distance from coil X-axis
                    if (0 < dx && dx < 0.1 && dx < diam / bigCoilRotFactor)
                    {
                        // isn't done if dx1 or dx2 is zero
                        angle = Math.PI / 4;
                        return(true);
                    }
                    else if (0.1 < dx && dx < 0.3 || (!diagCoil && (0.05 < dDiagX && dDiagX < 0.1 || dDiagX < 0.01)))
                    {
                        angle = CalculatePinPairAngle(src, 0, 1);
                        return(true);
                    }
                    var dy     = Math.Abs(center.Y) / diam;
                    var dDiagY = Math.Abs(cornerDx - dy);
                    // same small distance from coil Y-axis
                    if (0 < dy && dy < 0.1 && dy < diam / bigCoilRotFactor)
                    {
                        angle = Math.PI / 4;
                        return(true);
                    }
                    else if (0.1 < dy && dy < 0.3 || (!diagCoil && (0.05 < dDiagY && dDiagY < 0.1 || dDiagY < 0.01)))
                    {
                        angle = CalculatePinPairAngle(src, 0, 1);
                        return(true);
                    }
                    angle = 0;
                    return(true);
                }
                angle = CalculatePinPairAngle(src, 0, 1);
                return(true);

            case 3:
            case 4:
                angle = CalculatePinPairAngle(src, 0, 1);
                return(true);
            }
            return(false);
        }
Exemplo n.º 21
0
 private bool DetectJ(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
 {
     angle = 0;
     // J-specific
     aspect = 0;
     if (src.PinCount >= 24)
     {
         if (CheckPinRow(src, 1, 3, 3)) // pci/ddr
         {
             angle = CalculatePinPairAngle(src, 1, 7);
             return(true);
         }
     }
     if (src.PinCount >= 6)
     {
         if (CheckPinRow(src, 0, 3, 2))                           // dual row
         {
             if (src.PinCount >= 24 && CheckPinRow(src, 0, 6, 2)) // try get more accurate angle
             {
                 angle = CalculatePinPairAngle(src, 0, 10);
             }
             else
             {
                 angle = CalculatePinPairAngle(src, 0, 4);
             }
             return(true);
         }
     }
     if (src.PinCount >= 5)
     {
         if (CheckPinRow(src, 1, 3, 1)) // single row
         {
             angle = CalculatePinPairAngle(src, 1, 3);
             return(true);
         }
         if (CheckPinRow(src, 0, 3, 1)) // single row
         {
             if (CheckDualRow(src, ref angle, 0, 2, 3, 4))
             {
                 return(true);
             }
         }
     }
     if (src.PinCount == 4)
     {
         if (CheckPinRow(src, 0, 3, 1)) // single row
         {
             angle = CalculatePinPairAngle(src, 1, 3);
             return(true);
         }
         // 2+2gnd
         if (CheckDualRow(src, ref angle, 0, 1, 2, 3))
         {
             return(true);
         }
     }
     if (src.PinCount == 3)
     {
         angle = CalculatePinPairAngle(src, 0, 2);
         return(true);
     }
     if (src.PinCount == 2)
     {
         angle = CalculatePinPairAngle(src, 0, 1);
         return(true);
     }
     angle = 0;
     return(false);
 }
Exemplo n.º 22
0
        private OBB CalculatePartOBB(SceneObjects.Part src)
        {
            char c = '\0';

            if (src.Name.Length > 0)
            {
                c = src.Name[0];
            }
            double growR        = 1.0;
            double adjustAspect = 1.0 / 2; // 1.1/2
            var    obb          = OBB.Empty;

            AdjustPart(src, ref obb, ref adjustAspect, ref growR);
            for (int j = src.FirstPin; j < src.FirstPin + src.PinCount; j++)
            {
                var p = Root.Scene.Pins[j];
                if (p.Side == src.Side)
                {
                    obb.Merge(p.Location);
                }
                if (p.Inverse != null && p.Inverse.Side == src.Side)
                {
                    obb.Merge(p.Inverse.Location);
                }
            }
            if (growR > 0) // outer box (+radius)
            {
                obb.Grow(Root.Scene.Options.PinBoxRadius * growR);
            }
            if (adjustAspect != 0)
            {
                var center       = obb.Center;
                var w            = obb.Width;
                var h            = obb.Height;
                var lowRefAspect = w / h < Math.Abs(adjustAspect) || h / w < Math.Abs(adjustAspect);
                if (lowRefAspect || adjustAspect < 0)
                {
                    var     turn = obb.Turn;
                    Vector2 boxOffset;
                    if (adjustAspect > 0)
                    {
                        if (w > h)
                        {
                            boxOffset = new Vector2(w / 2, w * adjustAspect / 2);
                        }
                        else
                        {
                            boxOffset = new Vector2(h * adjustAspect / 2, h / 2);
                        }
                    }
                    else
                    {
                        adjustAspect *= -1;
                        if (lowRefAspect)
                        {
                            if (w > h)
                            {
                                boxOffset = new Vector2(w / 2, w * adjustAspect / 2);
                            }
                            else
                            {
                                boxOffset = new Vector2(h * adjustAspect / 2, h / 2);
                            }
                        }
                        else
                        {
                            var minRefSz = Math.Min(w, h);
                            if (w > h)
                            {
                                boxOffset = new Vector2(minRefSz / adjustAspect / 2, minRefSz / 2);
                            }
                            else
                            {
                                boxOffset = new Vector2(minRefSz / 2, minRefSz / adjustAspect / 2);
                            }
                        }
                    }
                    obb.Set(center - boxOffset, center + boxOffset, turn);
                }
            }
            return(obb);
        }
Exemplo n.º 23
0
        private bool DetectU(SceneObjects.Part src, ref double aspect, ref double growR, out double angle)
        {
            if (src.PinCount < 2)
            {
                angle = 0;
                return(false);
            }
            angle = 0;
            // U-specific settings
            growR = 0;
            var defaultAspect = aspect;

            aspect = 0;
            switch (src.PinCount)
            {
            case 2:
                aspect = defaultAspect;
                angle  = CalculatePinPairAngle(src, 0, 1);
                return(true);

            case 3:
                angle = CalculatePinPairAngle(src, 0, 1);
                return(true);

            case 4:
            case 5:
                if (CheckPinRow(src, 0, 3))
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                    return(true);
                }
                if (CheckDualRow(src, ref angle, 0, 1, 2, 3))
                {
                    return(true);
                }
                break;

            case 6: // 2(3)
            case 7: // 2(3) +gnd
                if (CheckPinRow(src, 0, 3) && CheckPinRow(src, 3, 3))
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                    return(true);
                }
                break;

            case 8:
                if (CheckPinRow(src, 0, 4) && CheckPinRow(src, 4, 4))
                {
                    angle = CalculatePinPairAngle(src, 0, 3);
                    return(true);
                }
                break;

            case 9:
                if (CheckDualRow(src, ref angle, 0, 2, 3, 5))
                {
                    return(true);
                }
                goto case 8;

            case 20:                                                   // 2(2+8) (+gnd)
            case 21:
                if (CheckPinRow(src, 1, 8) && CheckPinRow(src, 11, 8)) // mux
                {
                    angle = CalculatePinPairAngle(src, 11, 18);
                    return(true);
                }
                break;

            case 14:
            case 15:
                if (CheckPinRow(src, 1, 5) && CheckPinRow(src, 8, 5)) // mux
                {
                    angle = CalculatePinPairAngle(src, 8, 12);
                    return(true);
                }
                break;

            case 16: // 2(4+4)
            {
                #region
                int good = 0;
                int pa = -1, pb = -1;
                if (CheckPinRow(src, 0, 4))
                {
                    pa = 0;
                    pb = 3;
                    good++;
                }
                if (CheckPinRow(src, 4, 4))
                {
                    pa = 4;
                    pb = 7;
                    good++;
                }
                if (CheckPinRow(src, 8, 4))
                {
                    pa = 8;
                    pb = 13;
                    good++;
                }
                if (CheckPinRow(src, 12, 4))
                {
                    pa = 12;
                    pb = 15;
                    good++;
                }
                if (good > 2)
                {
                    angle = CalculatePinPairAngle(src, pa, pb);
                    return(true);
                }
                #endregion
                goto case 17;
            }

            case 17:                                                  // 2(2+6) (+gnd)
                if (CheckPinRow(src, 1, 6) && CheckPinRow(src, 9, 6)) // mux
                {
                    angle = CalculatePinPairAngle(src, 9, 14);
                    return(true);
                }
                break;
            }
            if (src.PinCount >= 32)
            {
                if (CheckPinRow(src, 2, 4))
                {
                    angle = CalculatePinPairAngle(src, 2, 5);
                    return(true);
                }
            }
            if (src.PinCount >= 20)
            {
                if (CheckPinRow(src, 0, 5))
                {
                    angle = CalculatePinPairAngle(src, 0, 4);
                    return(true);
                }
            }
            if (src.PinCount > 10)
            {
                if (CheckPinRow(src, 0, 3))
                {
                    angle = CalculatePinPairAngle(src, 0, 2);
                }
                else if (CheckPinRow(src, 1, 3))
                {
                    angle = CalculatePinPairAngle(src, 1, 3);
                }
                else
                {
                    angle = 0;
                }
                return(true);
            }
            angle = 0.0;
            return(false);
        }